aboutsummaryrefslogtreecommitdiff
path: root/render/gles2/renderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/gles2/renderer.c')
-rw-r--r--render/gles2/renderer.c165
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);