From 95e86e675a7eef326958ab9047ff4ca0d0182cfc Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 20 Mar 2018 19:14:33 +0100 Subject: [PATCH] render/gles2: remove global state, use OpenGL debug extension --- include/render/gles2.h | 43 ++- include/wlr/render/interface.h | 10 +- include/wlr/render/wlr_texture.h | 2 +- render/glapi.txt | 5 + render/gles2/pixel_format.c | 8 +- render/gles2/renderer.c | 448 +++++++++++++++++++++---------- render/gles2/shaders.c | 148 +++++----- render/gles2/texture.c | 224 +++++++++------- render/wlr_renderer.c | 2 +- render/wlr_texture.c | 6 +- 10 files changed, 525 insertions(+), 371 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 0a4fb49f..9ff09065 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -17,17 +17,24 @@ extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; -struct pixel_format { +struct gles2_pixel_format { uint32_t wl_format; GLint gl_format, gl_type; int depth, bpp; - GLuint *shader; }; struct wlr_gles2_renderer { struct wlr_renderer wlr_renderer; struct wlr_egl *egl; + + struct { + GLuint quad; + GLuint ellipse; + GLuint tex_rgba; + GLuint tex_rgbx; + GLuint tex_ext; + } shaders; }; struct wlr_gles2_texture { @@ -35,37 +42,19 @@ struct wlr_gles2_texture { struct wlr_egl *egl; GLuint tex_id; - const struct pixel_format *pixel_format; + const struct gles2_pixel_format *pixel_format; EGLImageKHR image; GLenum target; }; -struct shaders { - bool initialized; - GLuint rgba, rgbx; - GLuint quad; - GLuint ellipse; - GLuint external; -}; - -extern struct shaders shaders; - -const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt); +const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt); struct wlr_texture *gles2_texture_create(); +struct wlr_gles2_texture *gles2_get_texture(struct wlr_texture *wlr_texture); -extern const GLchar quad_vertex_src[]; -extern const GLchar quad_fragment_src[]; -extern const GLchar ellipse_fragment_src[]; -extern const GLchar vertex_src[]; -extern const GLchar fragment_src_rgba[]; -extern const GLchar fragment_src_rgbx[]; -extern const GLchar fragment_src_external[]; - -bool _gles2_flush_errors(const char *file, int line); -#define gles2_flush_errors(...) \ - _gles2_flush_errors(wlr_strip_path(__FILE__), __LINE__) - -#define GL_CALL(func) func; gles2_flush_errors() +void gles2_push_marker(const char *file, const char *func); +void gles2_pop_marker(void); +#define GLES2_DEBUG_PUSH gles2_push_marker(wlr_strip_path(__FILE__), __func__) +#define GLES2_DEBUG_POP gles2_pop_marker() #endif diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index f0307230..da0aaec9 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -14,7 +14,7 @@ struct wlr_renderer_impl; struct wlr_renderer { - struct wlr_renderer_impl *impl; + const struct wlr_renderer_impl *impl; }; struct wlr_renderer_impl { @@ -44,7 +44,7 @@ struct wlr_renderer_impl { }; void wlr_renderer_init(struct wlr_renderer *renderer, - struct wlr_renderer_impl *impl); + const struct wlr_renderer_impl *impl); struct wlr_texture_impl { bool (*upload_pixels)(struct wlr_texture *texture, @@ -65,14 +65,12 @@ struct wlr_texture_impl { struct wl_resource *dmabuf_resource); void (*get_buffer_size)(struct wlr_texture *texture, struct wl_resource *resource, int *width, int *height); - void (*bind)(struct wlr_texture *texture); void (*destroy)(struct wlr_texture *texture); }; void wlr_texture_init(struct wlr_texture *texture, - struct wlr_texture_impl *impl); -void wlr_texture_bind(struct wlr_texture *texture); + const struct wlr_texture_impl *impl); void wlr_texture_get_buffer_size(struct wlr_texture *texture, - struct wl_resource *resource, int *width, int *height); + struct wl_resource *resource, int *width, int *height); #endif diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 49aa93d7..095097e6 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -9,7 +9,7 @@ struct wlr_texture_impl; struct wlr_texture { - struct wlr_texture_impl *impl; + const struct wlr_texture_impl *impl; bool valid; uint32_t format; diff --git a/render/glapi.txt b/render/glapi.txt index 02ac7dd8..a8e4aaba 100644 --- a/render/glapi.txt +++ b/render/glapi.txt @@ -10,3 +10,8 @@ eglCreatePlatformWindowSurfaceEXT -eglSwapBuffersWithDamageKHR -eglQueryDmaBufFormatsEXT -eglQueryDmaBufModifiersEXT +-eglDebugMessageControlKHR +-glDebugMessageCallbackKHR +-glDebugMessageControlKHR +-glPopDebugGroupKHR +-glPushDebugGroupKHR diff --git a/render/gles2/pixel_format.c b/render/gles2/pixel_format.c index a544077b..7c34896c 100644 --- a/render/gles2/pixel_format.c +++ b/render/gles2/pixel_format.c @@ -6,14 +6,13 @@ * The wayland formats are little endian while the GL formats are big endian, * so WL_SHM_FORMAT_ARGB8888 is actually compatible with GL_BGRA_EXT. */ -struct pixel_format formats[] = { +struct gles2_pixel_format formats[] = { { .wl_format = WL_SHM_FORMAT_ARGB8888, .depth = 32, .bpp = 32, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_BYTE, - .shader = &shaders.rgba }, { .wl_format = WL_SHM_FORMAT_XRGB8888, @@ -21,7 +20,6 @@ struct pixel_format formats[] = { .bpp = 32, .gl_format = GL_BGRA_EXT, .gl_type = GL_UNSIGNED_BYTE, - .shader = &shaders.rgbx }, { .wl_format = WL_SHM_FORMAT_XBGR8888, @@ -29,7 +27,6 @@ struct pixel_format formats[] = { .bpp = 32, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_BYTE, - .shader = &shaders.rgbx }, { .wl_format = WL_SHM_FORMAT_ABGR8888, @@ -37,12 +34,11 @@ struct pixel_format formats[] = { .bpp = 32, .gl_format = GL_RGBA, .gl_type = GL_UNSIGNED_BYTE, - .shader = &shaders.rgba }, }; // TODO: more pixel formats -const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt) { +const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt) { for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { if (formats[i].wl_format == fmt) { return &formats[i]; diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index f525869d..14eea666 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -2,145 +2,80 @@ #include #include #include +#include #include #include #include #include -#include #include #include +#include #include #include #include "render/gles2.h" #include "glapi.h" -struct shaders shaders; - -static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) { - *shader = GL_CALL(glCreateShader(type)); - int len = strlen(src); - GL_CALL(glShaderSource(*shader, 1, &src, &len)); - GL_CALL(glCompileShader(*shader)); - GLint success; - GL_CALL(glGetShaderiv(*shader, GL_COMPILE_STATUS, &success)); - if (success == GL_FALSE) { - GLint loglen; - GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen)); - GLchar msg[loglen]; - GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg)); - wlr_log(L_ERROR, "Shader compilation failed"); - wlr_log(L_ERROR, "%s", msg); - glDeleteShader(*shader); - return false; - } - return true; -} +static const struct wlr_renderer_impl renderer_impl; -static bool compile_program(const GLchar *vert_src, - const GLchar *frag_src, GLuint *program) { - GLuint vertex, fragment; - if (!compile_shader(GL_VERTEX_SHADER, vert_src, &vertex)) { - return false; - } - if (!compile_shader(GL_FRAGMENT_SHADER, frag_src, &fragment)) { - glDeleteShader(vertex); - return false; - } - *program = GL_CALL(glCreateProgram()); - GL_CALL(glAttachShader(*program, vertex)); - GL_CALL(glAttachShader(*program, fragment)); - GL_CALL(glLinkProgram(*program)); - GLint success; - GL_CALL(glGetProgramiv(*program, GL_LINK_STATUS, &success)); - if (success == GL_FALSE) { - GLint loglen; - GL_CALL(glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &loglen)); - GLchar msg[loglen]; - GL_CALL(glGetProgramInfoLog(*program, loglen, &loglen, msg)); - wlr_log(L_ERROR, "Program link failed"); - wlr_log(L_ERROR, "%s", msg); - glDeleteProgram(*program); - glDeleteShader(vertex); - glDeleteShader(fragment); - return false; - } - glDetachShader(*program, vertex); - glDetachShader(*program, fragment); - glDeleteShader(vertex); - glDeleteShader(fragment); - - return true; +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 renderer; } -static void init_default_shaders() { - if (shaders.initialized) { - return; - } - if (!compile_program(vertex_src, fragment_src_rgba, &shaders.rgba)) { - goto error; - } - if (!compile_program(vertex_src, fragment_src_rgbx, &shaders.rgbx)) { - goto error; - } - if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) { - goto error; - } - if (!compile_program(quad_vertex_src, ellipse_fragment_src, - &shaders.ellipse)) { - goto error; - } - if (glEGLImageTargetTexture2DOES) { - if (!compile_program(vertex_src, fragment_src_external, - &shaders.external)) { - goto error; - } - } - - wlr_log(L_DEBUG, "Compiled default shaders"); - shaders.initialized = true; - return; -error: - wlr_log(L_ERROR, "Failed to set up default shaders!"); -} +static void gles2_begin(struct wlr_renderer *wlr_renderer, + struct wlr_output *output) { + gles2_get_renderer(wlr_renderer); -static void init_globals() { - init_default_shaders(); -} + GLES2_DEBUG_PUSH; -static void wlr_gles2_begin(struct wlr_renderer *wlr_renderer, - struct wlr_output *output) { - GL_CALL(glViewport(0, 0, output->width, output->height)); + glViewport(0, 0, output->width, output->height); // enable transparency - GL_CALL(glEnable(GL_BLEND)); - GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // Note: maybe we should save output projection and remove some of the need + // XXX: maybe we should save output projection and remove some of the need // for users to sling matricies themselves + + GLES2_DEBUG_POP; } -static void wlr_gles2_end(struct wlr_renderer *wlr_renderer) { +static void gles2_end(struct wlr_renderer *wlr_renderer) { + gles2_get_renderer(wlr_renderer); // no-op } -static void wlr_gles2_clear(struct wlr_renderer *wlr_renderer, +static void gles2_clear(struct wlr_renderer *wlr_renderer, const float color[static 4]) { + gles2_get_renderer(wlr_renderer); + + GLES2_DEBUG_PUSH; glClearColor(color[0], color[1], color[2], color[3]); glClear(GL_COLOR_BUFFER_BIT); + GLES2_DEBUG_POP; } -static void wlr_gles2_scissor(struct wlr_renderer *wlr_renderer, +static void gles2_scissor(struct wlr_renderer *wlr_renderer, struct wlr_box *box) { + gles2_get_renderer(wlr_renderer); + + GLES2_DEBUG_PUSH; if (box != NULL) { glScissor(box->x, box->y, box->width, box->height); glEnable(GL_SCISSOR_TEST); } else { glDisable(GL_SCISSOR_TEST); } + GLES2_DEBUG_POP; } -static struct wlr_texture *wlr_gles2_texture_create( +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); @@ -160,69 +95,93 @@ static void draw_quad() { 0, 1, // bottom left }; - GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts)); - GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord)); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord); - GL_CALL(glEnableVertexAttribArray(0)); - GL_CALL(glEnableVertexAttribArray(1)); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); - GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - GL_CALL(glDisableVertexAttribArray(0)); - GL_CALL(glDisableVertexAttribArray(1)); + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); } -static bool wlr_gles2_render_texture_with_matrix( - struct wlr_renderer *wlr_renderer, struct wlr_texture *texture, +static bool gles2_render_texture_with_matrix( + struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture, const float matrix[static 9], float alpha) { - if (!texture || !texture->valid) { + 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) { + prog = renderer->shaders.tex_ext; + } else if (texture->pixel_format->wl_format == WL_SHM_FORMAT_XRGB8888 || + texture->pixel_format->wl_format == WL_SHM_FORMAT_XBGR8888) { + prog = renderer->shaders.tex_rgbx; + } + // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE float transposition[9]; wlr_matrix_transpose(transposition, matrix); - wlr_texture_bind(texture); - GL_CALL(glUniformMatrix3fv(0, 1, GL_FALSE, transposition)); - GL_CALL(glUniform1i(1, texture->inverted_y)); - GL_CALL(glUniform1f(3, alpha)); + 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); + glUseProgram(prog); + + glUniformMatrix3fv(0, 1, GL_FALSE, transposition); + glUniform1i(1, wlr_texture->inverted_y); + glUniform1f(3, alpha); draw_quad(); + GLES2_DEBUG_POP; return true; } -static void wlr_gles2_render_quad(struct wlr_renderer *wlr_renderer, +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); + // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE float transposition[9]; wlr_matrix_transpose(transposition, matrix); - GL_CALL(glUseProgram(shaders.quad)); - GL_CALL(glUniformMatrix3fv(0, 1, GL_FALSE, transposition)); - GL_CALL(glUniform4f(1, color[0], color[1], color[2], color[3])); + GLES2_DEBUG_PUSH; + glUseProgram(renderer->shaders.quad); + glUniformMatrix3fv(0, 1, GL_FALSE, transposition); + glUniform4f(1, color[0], color[1], color[2], color[3]); draw_quad(); + GLES2_DEBUG_POP; } -static void wlr_gles2_render_ellipse(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); + // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE float transposition[9]; wlr_matrix_transpose(transposition, matrix); - GL_CALL(glUseProgram(shaders.ellipse)); - GL_CALL(glUniformMatrix3fv(0, 1, GL_FALSE, transposition)); - GL_CALL(glUniform4f(1, color[0], color[1], color[2], color[3])); + GLES2_DEBUG_PUSH; + glUseProgram(renderer->shaders.ellipse); + glUniformMatrix3fv(0, 1, GL_FALSE, transposition); + glUniform4f(1, color[0], color[1], color[2], color[3]); draw_quad(); + GLES2_DEBUG_POP; } -static const enum wl_shm_format *wlr_gles2_formats( +static const enum wl_shm_format *gles2_formats( struct wlr_renderer *renderer, size_t *len) { - static enum wl_shm_format formats[] = { + static const enum wl_shm_format formats[] = { WL_SHM_FORMAT_ARGB8888, WL_SHM_FORMAT_XRGB8888, WL_SHM_FORMAT_ABGR8888, @@ -232,25 +191,29 @@ static const enum wl_shm_format *wlr_gles2_formats( return formats; } -static bool wlr_gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer, +static bool gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer, struct wl_resource *buffer) { - struct wlr_gles2_renderer *renderer = - (struct wlr_gles2_renderer *)wlr_renderer; + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + EGLint format; - return wlr_egl_query_buffer(renderer->egl, buffer, - EGL_TEXTURE_FORMAT, &format); + return wlr_egl_query_buffer(renderer->egl, buffer, EGL_TEXTURE_FORMAT, + &format); } -static bool wlr_gles2_read_pixels(struct wlr_renderer *renderer, +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) { - const struct pixel_format *fmt = gl_format_for_wl_format(wl_fmt); + gles2_get_renderer(wlr_renderer); + + const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt); if (fmt == NULL) { wlr_log(L_ERROR, "Cannot read pixels: unsupported pixel format"); return false; } + GLES2_DEBUG_PUSH; + // Make sure any pending drawing is finished before we try to read it glFinish(); @@ -262,38 +225,225 @@ static bool wlr_gles2_read_pixels(struct wlr_renderer *renderer, fmt->gl_type, p + i * stride + dst_x * fmt->bpp / 8); } + GLES2_DEBUG_POP; + return true; } -static bool wlr_gles2_format_supported(struct wlr_renderer *r, +static bool gles2_format_supported(struct wlr_renderer *r, enum wl_shm_format wl_fmt) { - return gl_format_for_wl_format(wl_fmt); + return gles2_format_from_wl(wl_fmt) != NULL; +} + +static void gles2_destroy(struct wlr_renderer *wlr_renderer) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + + wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); + + GLES2_DEBUG_PUSH; + glDeleteProgram(renderer->shaders.quad); + glDeleteProgram(renderer->shaders.ellipse); + glDeleteProgram(renderer->shaders.tex_rgba); + glDeleteProgram(renderer->shaders.tex_rgbx); + glDeleteProgram(renderer->shaders.tex_ext); + GLES2_DEBUG_POP; + + if (glDebugMessageCallbackKHR) { + glDisable(GL_DEBUG_OUTPUT_KHR); + glDebugMessageCallbackKHR(NULL, NULL); + } + + free(renderer); } -static struct wlr_renderer_impl wlr_renderer_impl = { - .begin = wlr_gles2_begin, - .end = wlr_gles2_end, - .clear = wlr_gles2_clear, - .scissor = wlr_gles2_scissor, - .texture_create = wlr_gles2_texture_create, - .render_texture_with_matrix = wlr_gles2_render_texture_with_matrix, - .render_quad = wlr_gles2_render_quad, - .render_ellipse = wlr_gles2_render_ellipse, - .formats = wlr_gles2_formats, - .buffer_is_drm = wlr_gles2_buffer_is_drm, - .read_pixels = wlr_gles2_read_pixels, - .format_supported = wlr_gles2_format_supported, +static const struct wlr_renderer_impl renderer_impl = { + .destroy = gles2_destroy, + .begin = gles2_begin, + .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_formats, + .buffer_is_drm = gles2_buffer_is_drm, + .read_pixels = gles2_read_pixels, + .format_supported = gles2_format_supported, }; +void gles2_push_marker(const char *file, const char *func) { + if (!glPushDebugGroupKHR) { + return; + } + + int len = snprintf(NULL, 0, "%s:%s", file, func) + 1; + char str[len]; + snprintf(str, len, "%s:%s", file, func); + glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 1, -1, str); +} + +void gles2_pop_marker(void) { + if (glPopDebugGroupKHR) { + glPopDebugGroupKHR(); + } +} + +static log_importance_t gles2_log_importance_to_wlr(GLenum type) { + switch (type) { + case GL_DEBUG_TYPE_ERROR_KHR: return L_ERROR; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR: return L_DEBUG; + 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_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; + } +} + +static void gles2_log(GLenum src, GLenum type, GLuint id, GLenum severity, + GLsizei len, const GLchar *msg, const void *user) { + _wlr_log(gles2_log_importance_to_wlr(type), "[GLES2] %s", msg); +} + +static GLuint compile_shader(GLuint type, const GLchar *src) { + GLES2_DEBUG_PUSH; + + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &src, NULL); + glCompileShader(shader); + + GLint ok; + glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); + if (ok == GL_FALSE) { + glDeleteShader(shader); + shader = 0; + } + + GLES2_DEBUG_POP; + return shader; +} + +static GLuint link_program(const GLchar *vert_src, const GLchar *frag_src) { + GLES2_DEBUG_PUSH; + + GLuint vert = compile_shader(GL_VERTEX_SHADER, vert_src); + if (!vert) { + goto error; + } + + GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src); + if (!frag) { + glDeleteShader(vert); + goto error; + } + + GLuint prog = glCreateProgram(); + glAttachShader(prog, vert); + glAttachShader(prog, frag); + glLinkProgram(prog); + + glDetachShader(prog, vert); + glDetachShader(prog, frag); + glDeleteShader(vert); + glDeleteShader(frag); + + GLint ok; + glGetProgramiv(prog, GL_LINK_STATUS, &ok); + if (ok == GL_FALSE) { + glDeleteProgram(prog); + goto error; + } + + GLES2_DEBUG_POP; + return prog; + +error: + GLES2_DEBUG_POP; + return 0; +} + +extern const GLchar quad_vertex_src[]; +extern const GLchar quad_fragment_src[]; +extern const GLchar ellipse_fragment_src[]; +extern const GLchar tex_vertex_src[]; +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) { - init_globals(); - struct wlr_gles2_renderer *renderer; - if (!(renderer = calloc(1, sizeof(struct wlr_gles2_renderer)))) { + struct wlr_gles2_renderer *renderer = + calloc(1, sizeof(struct wlr_gles2_renderer)); + if (renderer == NULL) { return NULL; } - wlr_renderer_init(&renderer->wlr_renderer, &wlr_renderer_impl); + wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl); renderer->egl = wlr_backend_get_egl(backend); + wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); + + if (glDebugMessageCallbackKHR && glDebugMessageControlKHR) { + glEnable(GL_DEBUG_OUTPUT_KHR); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); + glDebugMessageCallbackKHR(gles2_log, NULL); + + // Silence unwanted message types + glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_POP_GROUP_KHR, + GL_DONT_CARE, 0, NULL, GL_FALSE); + glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PUSH_GROUP_KHR, + GL_DONT_CARE, 0, NULL, GL_FALSE); + } + + GLES2_DEBUG_PUSH; + + renderer->shaders.quad = link_program(quad_vertex_src, quad_fragment_src); + if (!renderer->shaders.quad) { + goto error; + } + renderer->shaders.ellipse = + link_program(quad_vertex_src, ellipse_fragment_src); + if (!renderer->shaders.ellipse) { + goto error; + } + renderer->shaders.tex_rgba = + link_program(tex_vertex_src, tex_fragment_src_rgba); + if (!renderer->shaders.tex_rgba) { + goto error; + } + renderer->shaders.tex_rgbx = + link_program(tex_vertex_src, tex_fragment_src_rgbx); + if (!renderer->shaders.tex_rgbx) { + goto error; + } + if (glEGLImageTargetTexture2DOES) { + renderer->shaders.tex_ext = + link_program(tex_vertex_src, tex_fragment_src_external); + if (!renderer->shaders.tex_ext) { + goto error; + } + } + + GLES2_DEBUG_POP; return &renderer->wlr_renderer; + +error: + glDeleteProgram(renderer->shaders.quad); + glDeleteProgram(renderer->shaders.ellipse); + glDeleteProgram(renderer->shaders.tex_rgba); + glDeleteProgram(renderer->shaders.tex_rgbx); + glDeleteProgram(renderer->shaders.tex_ext); + + GLES2_DEBUG_POP; + + if (glDebugMessageCallbackKHR) { + glDisable(GL_DEBUG_OUTPUT_KHR); + glDebugMessageCallbackKHR(NULL, NULL); + } + + free(renderer); + return NULL; } diff --git a/render/gles2/shaders.c b/render/gles2/shaders.c index 30e12e4c..ba3bd971 100644 --- a/render/gles2/shaders.c +++ b/render/gles2/shaders.c @@ -3,86 +3,88 @@ // Colored quads const GLchar quad_vertex_src[] = -"uniform mat3 proj;" -"uniform vec4 color;" -"attribute vec2 pos;" -"attribute vec2 texcoord;" -"varying vec4 v_color;" -"varying vec2 v_texcoord;" -"" -"void main() {" -" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);" -" v_color = color;" -" v_texcoord = texcoord;" -"}"; +"uniform mat3 proj;\n" +"uniform vec4 color;\n" +"attribute vec2 pos;\n" +"attribute vec2 texcoord;\n" +"varying vec4 v_color;\n" +"varying vec2 v_texcoord;\n" +"\n" +"void main() {\n" +" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n" +" v_color = color;\n" +" v_texcoord = texcoord;\n" +"}\n"; const GLchar quad_fragment_src[] = -"precision mediump float;" -"varying vec4 v_color;" -"varying vec2 v_texcoord;" -"" -"void main() {" -" gl_FragColor = v_color;" -"}"; +"precision mediump float;\n" +"varying vec4 v_color;\n" +"varying vec2 v_texcoord;\n" +"\n" +"void main() {\n" +" gl_FragColor = v_color;\n" +"}\n"; // Colored ellipses const GLchar ellipse_fragment_src[] = -"precision mediump float;" -"varying vec4 v_color;" -"varying vec2 v_texcoord;" -"" -"void main() {" -" float l = length(v_texcoord - vec2(0.5, 0.5));" -" if (l > 0.5) discard;" -" gl_FragColor = v_color;" -"}"; +"precision mediump float;\n" +"varying vec4 v_color;\n" +"varying vec2 v_texcoord;\n" +"\n" +"void main() {\n" +" float l = length(v_texcoord - vec2(0.5, 0.5));\n" +" if (l > 0.5) {\n" +" discard;\n" +" }\n" +" gl_FragColor = v_color;\n" +"}\n"; // Textured quads -const GLchar vertex_src[] = -"uniform mat3 proj;" -"uniform bool invert_y;" -"attribute vec2 pos;" -"attribute vec2 texcoord;" -"varying vec2 v_texcoord;" -"" -"void main() {" -" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);" -" if (invert_y) {" -" v_texcoord = vec2(texcoord.s, 1.0 - texcoord.t);" -" } else {" -" v_texcoord = texcoord;" -" }" -"}"; +const GLchar tex_vertex_src[] = +"uniform mat3 proj;\n" +"uniform bool invert_y;\n" +"attribute vec2 pos;\n" +"attribute vec2 texcoord;\n" +"varying vec2 v_texcoord;\n" +"\n" +"void main() {\n" +" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n" +" if (invert_y) {\n" +" v_texcoord = vec2(texcoord.s, 1.0 - texcoord.t);\n" +" } else {\n" +" v_texcoord = texcoord;\n" +" }\n" +"}\n"; -const GLchar fragment_src_rgba[] = -"precision mediump float;" -"varying vec2 v_texcoord;" -"uniform sampler2D tex;" -"uniform float alpha;" -"" -"void main() {" -" gl_FragColor = alpha * texture2D(tex, v_texcoord);" -"}"; +const GLchar tex_fragment_src_rgba[] = +"precision mediump float;\n" +"varying vec2 v_texcoord;\n" +"uniform sampler2D tex;\n" +"uniform float alpha;\n" +"\n" +"void main() {\n" +" gl_FragColor = alpha * texture2D(tex, v_texcoord);\n" +"}\n"; -const GLchar fragment_src_rgbx[] = -"precision mediump float;" -"varying vec2 v_texcoord;" -"uniform sampler2D tex;" -"uniform float alpha;" -"" -"void main() {" -" gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;" -" gl_FragColor.a = alpha;" -"}"; +const GLchar tex_fragment_src_rgbx[] = +"precision mediump float;\n" +"varying vec2 v_texcoord;\n" +"uniform sampler2D tex;\n" +"uniform float alpha;\n" +"\n" +"void main() {\n" +" gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;\n" +" gl_FragColor.a = alpha;\n" +"}\n"; -const GLchar fragment_src_external[] = -"#extension GL_OES_EGL_image_external : require\n" -"precision mediump float;" -"varying vec2 v_texcoord;" -"uniform samplerExternalOES texture0;" -"uniform float alpha;" -"" -"void main() {" -" vec4 col = texture2D(texture0, v_texcoord);" -" gl_FragColor = vec4(col.rgb, col.a * alpha);" -"}"; +const GLchar tex_fragment_src_external[] = +"#extension GL_OES_EGL_image_external : require\n\n" +"precision mediump float;\n" +"varying vec2 v_texcoord;\n" +"uniform samplerExternalOES texture0;\n" +"uniform float alpha;\n" +"\n" +"void main() {\n" +" vec4 col = texture2D(texture0, v_texcoord);\n" +" gl_FragColor = vec4(col.rgb, col.a * alpha);\n" +"}\n"; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 99f153b8..e21bd77f 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -13,33 +13,39 @@ #include "render/gles2.h" #include "util/signal.h" -static struct pixel_format external_pixel_format = { +static struct gles2_pixel_format external_pixel_format = { .wl_format = 0, .depth = 0, .bpp = 0, .gl_format = 0, .gl_type = 0, - .shader = &shaders.external }; -static void gles2_texture_ensure_texture(struct wlr_gles2_texture *texture, +static void gles2_texture_ensure(struct wlr_gles2_texture *texture, GLenum target) { if (texture->tex_id) { return; } texture->target = target; - GL_CALL(glGenTextures(1, &texture->tex_id)); - GL_CALL(glBindTexture(target, texture->tex_id)); - GL_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GL_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + 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 bool gles2_texture_upload_pixels(struct wlr_texture *_texture, +static const struct wlr_texture_impl texture_impl; + +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 *texture = (struct wlr_gles2_texture *)_texture; - assert(texture); - const struct pixel_format *fmt = gl_format_for_wl_format(format); + 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; @@ -49,44 +55,50 @@ static bool gles2_texture_upload_pixels(struct wlr_texture *_texture, texture->wlr_texture.format = format; texture->pixel_format = fmt; - gles2_texture_ensure_texture(texture, GL_TEXTURE_2D); - GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); - GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride)); - GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, - fmt->gl_format, fmt->gl_type, pixels)); + 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; } -static bool gles2_texture_update_pixels(struct wlr_texture *_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) { - struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; - assert(texture); + 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); + return gles2_texture_upload_pixels(&texture->wlr_texture, format, + stride, width, height, pixels); } - const struct pixel_format *fmt = texture->pixel_format; - GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); - GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y)); - GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, - fmt->gl_format, fmt->gl_type, pixels)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); + 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; } -static bool gles2_texture_upload_shm(struct wlr_texture *_texture, +static bool gles2_texture_upload_shm(struct wlr_texture *wlr_texture, uint32_t format, struct wl_shm_buffer *buffer) { - struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; - const struct pixel_format *fmt = gl_format_for_wl_format(format); + 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, "Unsupported pixel format %"PRIu32" for this texture", format); @@ -102,23 +114,26 @@ static bool gles2_texture_upload_shm(struct wlr_texture *_texture, texture->wlr_texture.format = format; texture->pixel_format = fmt; - gles2_texture_ensure_texture(texture, GL_TEXTURE_2D); - GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); - GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); - GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, - fmt->gl_format, fmt->gl_type, pixels)); + 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; } -static bool gles2_texture_update_shm(struct wlr_texture *_texture, +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 = (struct wlr_gles2_texture *)_texture; + 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 assert(texture); @@ -127,28 +142,30 @@ static bool gles2_texture_update_shm(struct wlr_texture *_texture, /* || unpack not supported */) { return gles2_texture_upload_shm(&texture->wlr_texture, format, buffer); } - const struct pixel_format *fmt = texture->pixel_format; + 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); - GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); - GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y)); - GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, - fmt->gl_format, fmt->gl_type, pixels)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); - GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); + 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_SKIP_PIXELS_EXT, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); + GLES2_DEBUG_POP; wl_shm_buffer_end_access(buffer); return true; } -static bool gles2_texture_upload_drm(struct wlr_texture *_tex, +static bool gles2_texture_upload_drm(struct wlr_texture *wlr_texture, struct wl_resource *buf) { - struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)_tex; + struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); if (!glEGLImageTargetTexture2DOES) { return false; } @@ -160,9 +177,9 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, } wlr_egl_query_buffer(tex->egl, buf, EGL_WIDTH, - (EGLint*)&tex->wlr_texture.width); + (EGLint*)&tex->wlr_texture.width); wlr_egl_query_buffer(tex->egl, buf, EGL_HEIGHT, - (EGLint*)&tex->wlr_texture.height); + (EGLint*)&tex->wlr_texture.height); EGLint inverted_y; if (wlr_egl_query_buffer(tex->egl, buf, EGL_WAYLAND_Y_INVERTED_WL, @@ -171,12 +188,12 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, } GLenum target; - const struct pixel_format *pf; + const struct gles2_pixel_format *pf; switch (format) { case EGL_TEXTURE_RGB: case EGL_TEXTURE_RGBA: target = GL_TEXTURE_2D; - pf = gl_format_for_wl_format(WL_SHM_FORMAT_ARGB8888); + pf = gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888); break; case EGL_TEXTURE_EXTERNAL_WL: target = GL_TEXTURE_EXTERNAL_OES; @@ -187,8 +204,11 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, return false; } - gles2_texture_ensure_texture(tex, target); - GL_CALL(glBindTexture(GL_TEXTURE_2D, tex->tex_id)); + 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 }; if (tex->image) { @@ -202,18 +222,20 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, return false; } - GL_CALL(glActiveTexture(GL_TEXTURE0)); - GL_CALL(glBindTexture(target, tex->tex_id)); - GL_CALL(glEGLImageTargetTexture2DOES(target, tex->image)); + 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_tex, +static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_texture, EGLImageKHR image, uint32_t width, uint32_t height) { - struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)wlr_tex; + struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); tex->image = image; tex->pixel_format = &external_pixel_format; @@ -221,20 +243,21 @@ static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex, tex->wlr_texture.width = width; tex->wlr_texture.height = height; - gles2_texture_ensure_texture(tex, GL_TEXTURE_2D); - - GL_CALL(glActiveTexture(GL_TEXTURE0)); - GL_CALL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id)); - GL_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image)); + 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; } -static bool gles2_texture_upload_dmabuf(struct wlr_texture *_tex, +static bool gles2_texture_upload_dmabuf(struct wlr_texture *wlr_texture, struct wl_resource *dmabuf_resource) { - struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)_tex; - struct wlr_dmabuf_buffer *dmabuf = wlr_dmabuf_buffer_from_buffer_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); if (!tex->egl->egl_exts.dmabuf_import) { wlr_log(L_ERROR, "Want dmabuf but extension not present"); @@ -249,17 +272,19 @@ static bool gles2_texture_upload_dmabuf(struct wlr_texture *_tex, } if (wlr_dmabuf_buffer_has_inverted_y(dmabuf)) { - _tex->inverted_y = true; + wlr_texture->inverted_y = true; } GLenum target = GL_TEXTURE_2D; - const struct pixel_format *pf = - gl_format_for_wl_format(WL_SHM_FORMAT_ARGB8888); - gles2_texture_ensure_texture(tex, target); - GL_CALL(glBindTexture(target, tex->tex_id)); + const struct gles2_pixel_format *pf = + gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888); + 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); - GL_CALL(glActiveTexture(GL_TEXTURE0)); - GL_CALL(glEGLImageTargetTexture2DOES(target, tex->image)); + glActiveTexture(GL_TEXTURE0); + glEGLImageTargetTexture2DOES(target, tex->image); + GLES2_DEBUG_POP; tex->pixel_format = pf; tex->wlr_texture.valid = true; return true; @@ -271,15 +296,15 @@ static bool gles2_texture_get_dmabuf_size(struct wlr_texture *texture, struct return false; } - struct wlr_dmabuf_buffer *dmabuf = wlr_dmabuf_buffer_from_buffer_resource( - resource); + 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) { +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; @@ -288,14 +313,13 @@ static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct } if (!wlr_egl_query_buffer(tex->egl, resource, EGL_WIDTH, (EGLint*)width)) { - if (!gles2_texture_get_dmabuf_size(texture, resource, - width, height)) { + 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); + wlr_egl_query_buffer(tex->egl, resource, EGL_HEIGHT, (EGLint*)height); return; } @@ -304,20 +328,15 @@ static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct *height = wl_shm_buffer_get_height(buffer); } -static void gles2_texture_bind(struct wlr_texture *_texture) { - struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; - - GL_CALL(glBindTexture(texture->target, texture->tex_id)); - GL_CALL(glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GL_CALL(glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GL_CALL(glUseProgram(*texture->pixel_format->shader)); -} +static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { + struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); -static void gles2_texture_destroy(struct wlr_texture *_texture) { - struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; - wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal, &texture->wlr_texture); + wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal, + &texture->wlr_texture); if (texture->tex_id) { - GL_CALL(glDeleteTextures(1, &texture->tex_id)); + GLES2_DEBUG_PUSH; + glDeleteTextures(1, &texture->tex_id); + GLES2_DEBUG_POP; } if (texture->image) { @@ -327,7 +346,7 @@ static void gles2_texture_destroy(struct wlr_texture *_texture) { free(texture); } -static struct wlr_texture_impl wlr_texture_impl = { +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, @@ -336,7 +355,6 @@ static struct wlr_texture_impl wlr_texture_impl = { .upload_dmabuf = gles2_texture_upload_dmabuf, .upload_eglimage = gles2_texture_upload_eglimage, .get_buffer_size = gles2_texture_get_buffer_size, - .bind = gles2_texture_bind, .destroy = gles2_texture_destroy, }; @@ -345,7 +363,7 @@ struct wlr_texture *gles2_texture_create(struct wlr_egl *egl) { if (!(texture = calloc(1, sizeof(struct wlr_gles2_texture)))) { return NULL; } - wlr_texture_init(&texture->wlr_texture, &wlr_texture_impl); + wlr_texture_init(&texture->wlr_texture, &texture_impl); texture->egl = egl; return &texture->wlr_texture; } diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 21a7901a..79e0b5d5 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -5,7 +5,7 @@ #include void wlr_renderer_init(struct wlr_renderer *renderer, - struct wlr_renderer_impl *impl) { + const struct wlr_renderer_impl *impl) { renderer->impl = impl; } diff --git a/render/wlr_texture.c b/render/wlr_texture.c index a5d0abde..33c91822 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -4,7 +4,7 @@ #include void wlr_texture_init(struct wlr_texture *texture, - struct wlr_texture_impl *impl) { + const struct wlr_texture_impl *impl) { texture->impl = impl; wl_signal_init(&texture->destroy_signal); } @@ -17,10 +17,6 @@ void wlr_texture_destroy(struct wlr_texture *texture) { } } -void wlr_texture_bind(struct wlr_texture *texture) { - texture->impl->bind(texture); -} - bool wlr_texture_upload_pixels(struct wlr_texture *texture, uint32_t format, int stride, int width, int height, const unsigned char *pixels) { return texture->impl->upload_pixels(texture, format, stride,