summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kmscon_conf.c2
-rw-r--r--src/kmscon_main.c6
-rw-r--r--src/uterm_drm3d_internal.h100
-rw-r--r--src/uterm_drm3d_render.c495
-rw-r--r--src/uterm_drm3d_video.c (renamed from src/uterm_video_drm.c)498
-rw-r--r--src/uterm_video.c2
-rw-r--r--src/uterm_video.h6
-rw-r--r--src/uterm_video_internal.h2
8 files changed, 615 insertions, 496 deletions
diff --git a/src/kmscon_conf.c b/src/kmscon_conf.c
index d0f98df..e3bd225 100644
--- a/src/kmscon_conf.c
+++ b/src/kmscon_conf.c
@@ -447,7 +447,7 @@ static int aftercheck_drm(struct conf_option *opt, int argc, char **argv,
* enabled but will still correctly use fbdev devices so we can then
* remove this check. */
if (conf->drm) {
- if (!uterm_video_available(UTERM_VIDEO_DRM) &&
+ if (!uterm_video_available(UTERM_VIDEO_DRM3D) &&
!uterm_video_available(UTERM_VIDEO_DRM2D)) {
log_info("no DRM runtime support available; disabling --drm");
conf->drm = false;
diff --git a/src/kmscon_main.c b/src/kmscon_main.c
index b223b35..834c227 100644
--- a/src/kmscon_main.c
+++ b/src/kmscon_main.c
@@ -355,7 +355,7 @@ static int app_seat_add_video(struct app_seat *seat,
if (type == UTERM_MONITOR_DRM) {
if (seat->conf->hwaccel)
- mode = UTERM_VIDEO_DRM;
+ mode = UTERM_VIDEO_DRM3D;
else
mode = UTERM_VIDEO_DRM2D;
} else {
@@ -364,8 +364,8 @@ static int app_seat_add_video(struct app_seat *seat,
ret = uterm_video_new(&vid->video, seat->app->eloop, node, mode);
if (ret) {
- if (mode == UTERM_VIDEO_DRM) {
- log_info("cannot create drm device %s on seat %s (%d); trying drm2d mode",
+ if (mode == UTERM_VIDEO_DRM3D) {
+ log_info("cannot create drm3d device %s on seat %s (%d); trying drm2d mode",
vid->node, seat->name, ret);
ret = uterm_video_new(&vid->video, seat->app->eloop,
node, UTERM_VIDEO_DRM2D);
diff --git a/src/uterm_drm3d_internal.h b/src/uterm_drm3d_internal.h
new file mode 100644
index 0000000..49fcd7e
--- /dev/null
+++ b/src/uterm_drm3d_internal.h
@@ -0,0 +1,100 @@
+/*
+ * uterm - Linux User-Space Terminal drm3d module
+ *
+ * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Internal definitions */
+
+#ifndef UTERM_DRM3D_INTERNAL_H
+#define UTERM_DRM3D_INTERNAL_H
+
+#define EGL_EGLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gbm.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include "uterm_video.h"
+
+struct uterm_drm3d_rb {
+ struct uterm_display *disp;
+ struct gbm_bo *bo;
+ uint32_t fb;
+};
+
+struct uterm_drm3d_display {
+ struct gbm_surface *gbm;
+ EGLSurface surface;
+ struct uterm_drm3d_rb *current;
+ struct uterm_drm3d_rb *next;
+};
+
+struct uterm_drm3d_video {
+ struct gbm_device *gbm;
+ EGLDisplay disp;
+ EGLConfig conf;
+ EGLContext ctx;
+
+ unsigned int sinit;
+ bool supports_rowlen;
+ GLuint tex;
+
+ struct gl_shader *fill_shader;
+ GLuint uni_fill_proj;
+
+ struct gl_shader *blend_shader;
+ GLuint uni_blend_proj;
+ GLuint uni_blend_tex;
+ GLuint uni_blend_fgcol;
+ GLuint uni_blend_bgcol;
+
+ struct gl_shader *blit_shader;
+ GLuint uni_blit_proj;
+ GLuint uni_blit_tex;
+};
+
+int uterm_drm3d_display_use(struct uterm_display *disp, bool *opengl);
+void uterm_drm3d_deinit_shaders(struct uterm_video *video);
+int uterm_drm3d_display_blit(struct uterm_display *disp,
+ const struct uterm_video_buffer *buf,
+ unsigned int x, unsigned int y);
+int uterm_drm3d_display_fake_blendv(struct uterm_display *disp,
+ const struct uterm_video_blend_req *req,
+ size_t num);
+int uterm_drm3d_display_fill(struct uterm_display *disp,
+ uint8_t r, uint8_t g, uint8_t b,
+ unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height);
+
+#endif /* UTERM_DRM3D_INTERNAL_H */
diff --git a/src/uterm_drm3d_render.c b/src/uterm_drm3d_render.c
new file mode 100644
index 0000000..9a4bae9
--- /dev/null
+++ b/src/uterm_drm3d_render.c
@@ -0,0 +1,495 @@
+/*
+ * uterm - Linux User-Space Terminal
+ *
+ * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * DRM Video backend
+ */
+
+#define EGL_EGLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gbm.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include "eloop.h"
+#include "log.h"
+#include "static_gl.h"
+#include "uterm_drm_shared_internal.h"
+#include "uterm_drm3d_internal.h"
+#include "uterm_video.h"
+#include "uterm_video_internal.h"
+
+#define LOG_SUBSYSTEM "uterm_drm3d_render"
+
+extern const char *gl_static_fill_vert;
+extern const char *gl_static_fill_frag;
+extern const char *gl_static_blend_vert;
+extern const char *gl_static_blend_frag;
+extern const char *gl_static_blit_vert;
+extern const char *gl_static_blit_frag;
+
+static int init_shaders(struct uterm_video *video)
+{
+ struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
+ int ret;
+ char *fill_attr[] = { "position", "color" };
+ char *blend_attr[] = { "position", "texture_position" };
+ char *blit_attr[] = { "position", "texture_position" };
+
+ if (v3d->sinit == 1)
+ return -EFAULT;
+ else if (v3d->sinit == 2)
+ return 0;
+
+ v3d->sinit = 1;
+
+ ret = gl_shader_new(&v3d->fill_shader, gl_static_fill_vert,
+ gl_static_fill_frag, fill_attr, 2, log_llog);
+ if (ret)
+ return ret;
+
+ v3d->uni_fill_proj = gl_shader_get_uniform(v3d->fill_shader,
+ "projection");
+
+ ret = gl_shader_new(&v3d->blend_shader, gl_static_blend_vert,
+ gl_static_blend_frag, blend_attr, 2, log_llog);
+ if (ret)
+ return ret;
+
+ v3d->uni_blend_proj = gl_shader_get_uniform(v3d->blend_shader,
+ "projection");
+ v3d->uni_blend_tex = gl_shader_get_uniform(v3d->blend_shader,
+ "texture");
+ v3d->uni_blend_fgcol = gl_shader_get_uniform(v3d->blend_shader,
+ "fgcolor");
+ v3d->uni_blend_bgcol = gl_shader_get_uniform(v3d->blend_shader,
+ "bgcolor");
+
+ ret = gl_shader_new(&v3d->blit_shader, gl_static_blit_vert,
+ gl_static_blit_frag, blit_attr, 2, log_llog);
+ if (ret)
+ return ret;
+
+ v3d->uni_blit_proj = gl_shader_get_uniform(v3d->blit_shader,
+ "projection");
+ v3d->uni_blit_tex = gl_shader_get_uniform(v3d->blit_shader,
+ "texture");
+
+ gl_tex_new(&v3d->tex, 1);
+ v3d->sinit = 2;
+
+ return 0;
+}
+
+void uterm_drm3d_deinit_shaders(struct uterm_video *video)
+{
+ struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
+
+ if (v3d->sinit == 0)
+ return;
+
+ v3d->sinit = 0;
+ gl_tex_free(&v3d->tex, 1);
+ gl_shader_unref(v3d->blit_shader);
+ gl_shader_unref(v3d->blend_shader);
+ gl_shader_unref(v3d->fill_shader);
+}
+
+int uterm_drm3d_display_blit(struct uterm_display *disp,
+ const struct uterm_video_buffer *buf,
+ unsigned int x, unsigned int y)
+{
+ struct uterm_drm3d_video *v3d;
+ unsigned int sw, sh, tmp, width, height, i;
+ float mat[16];
+ float vertices[6 * 2], texpos[6 * 2];
+ int ret;
+ uint8_t *packed, *src, *dst;
+
+ if (!buf || buf->format != UTERM_FORMAT_XRGB32)
+ return -EINVAL;
+
+ v3d = uterm_drm_video_get_data(disp->video);
+ ret = uterm_drm3d_display_use(disp, NULL);
+ if (ret)
+ return ret;
+ ret = init_shaders(disp->video);
+ if (ret)
+ return ret;
+
+ sw = uterm_drm_mode_get_width(disp->current_mode);
+ sh = uterm_drm_mode_get_height(disp->current_mode);
+
+ vertices[0] = -1.0;
+ vertices[1] = -1.0;
+ vertices[2] = -1.0;
+ vertices[3] = +1.0;
+ vertices[4] = +1.0;
+ vertices[5] = +1.0;
+
+ vertices[6] = -1.0;
+ vertices[7] = -1.0;
+ vertices[8] = +1.0;
+ vertices[9] = +1.0;
+ vertices[10] = +1.0;
+ vertices[11] = -1.0;
+
+ texpos[0] = 0.0;
+ texpos[1] = 1.0;
+ texpos[2] = 0.0;
+ texpos[3] = 0.0;
+ texpos[4] = 1.0;
+ texpos[5] = 0.0;
+
+ texpos[6] = 0.0;
+ texpos[7] = 1.0;
+ texpos[8] = 1.0;
+ texpos[9] = 0.0;
+ texpos[10] = 1.0;
+ texpos[11] = 1.0;
+
+ tmp = x + buf->width;
+ if (tmp < x || x >= sw)
+ return -EINVAL;
+ if (tmp > sw)
+ width = sw - x;
+ else
+ width = buf->width;
+
+ tmp = y + buf->height;
+ if (tmp < y || y >= sh)
+ return -EINVAL;
+ if (tmp > sh)
+ height = sh - y;
+ else
+ height = buf->height;
+
+ glViewport(x, sh - y - height, width, height);
+ glDisable(GL_BLEND);
+
+ gl_shader_use(v3d->blit_shader);
+
+ gl_m4_identity(mat);
+ glUniformMatrix4fv(v3d->uni_blit_proj, 1, GL_FALSE, mat);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, v3d->tex);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ if (v3d->supports_rowlen) {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride / 4);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
+ GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ } else if (buf->stride == width) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
+ GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
+ } else {
+ packed = malloc(width * height);
+ if (!packed)
+ return -ENOMEM;
+
+ src = buf->data;
+ dst = packed;
+ for (i = 0; i < height; ++i) {
+ memcpy(dst, src, width * 4);
+ dst += width * 4;
+ src += buf->stride;
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
+ GL_BGRA_EXT, GL_UNSIGNED_BYTE, packed);
+
+ free(packed);
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glUniform1i(v3d->uni_blit_tex, 0);
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
+
+ if (gl_has_error(v3d->blit_shader)) {
+ log_warning("GL error");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int display_blend(struct uterm_display *disp,
+ const struct uterm_video_buffer *buf,
+ unsigned int x, unsigned int y,
+ uint8_t fr, uint8_t fg, uint8_t fb,
+ uint8_t br, uint8_t bg, uint8_t bb)
+{
+ struct uterm_drm3d_video *v3d;
+ unsigned int sw, sh, tmp, width, height, i;
+ float mat[16];
+ float vertices[6 * 2], texpos[6 * 2], fgcol[3], bgcol[3];
+ int ret;
+ uint8_t *packed, *src, *dst;
+
+ if (!buf || buf->format != UTERM_FORMAT_GREY)
+ return -EINVAL;
+
+ v3d = uterm_drm_video_get_data(disp->video);
+ ret = uterm_drm3d_display_use(disp, NULL);
+ if (ret)
+ return ret;
+ ret = init_shaders(disp->video);
+ if (ret)
+ return ret;
+
+ sw = uterm_drm_mode_get_width(disp->current_mode);
+ sh = uterm_drm_mode_get_height(disp->current_mode);
+
+ vertices[0] = -1.0;
+ vertices[1] = -1.0;
+ vertices[2] = -1.0;
+ vertices[3] = +1.0;
+ vertices[4] = +1.0;
+ vertices[5] = +1.0;
+
+ vertices[6] = -1.0;
+ vertices[7] = -1.0;
+ vertices[8] = +1.0;
+ vertices[9] = +1.0;
+ vertices[10] = +1.0;
+ vertices[11] = -1.0;
+
+ texpos[0] = 0.0;
+ texpos[1] = 1.0;
+ texpos[2] = 0.0;
+ texpos[3] = 0.0;
+ texpos[4] = 1.0;
+ texpos[5] = 0.0;
+
+ texpos[6] = 0.0;
+ texpos[7] = 1.0;
+ texpos[8] = 1.0;
+ texpos[9] = 0.0;
+ texpos[10] = 1.0;
+ texpos[11] = 1.0;
+
+ fgcol[0] = fr / 255.0;
+ fgcol[1] = fg / 255.0;
+ fgcol[2] = fb / 255.0;
+ bgcol[0] = br / 255.0;
+ bgcol[1] = bg / 255.0;
+ bgcol[2] = bb / 255.0;
+
+ tmp = x + buf->width;
+ if (tmp < x || x >= sw)
+ return -EINVAL;
+ if (tmp > sw)
+ width = sw - x;
+ else
+ width = buf->width;
+
+ tmp = y + buf->height;
+ if (tmp < y || y >= sh)
+ return -EINVAL;
+ if (tmp > sh)
+ height = sh - y;
+ else
+ height = buf->height;
+
+ glViewport(x, sh - y - height, width, height);
+ glDisable(GL_BLEND);
+
+ gl_shader_use(v3d->blend_shader);
+
+ gl_m4_identity(mat);
+ glUniformMatrix4fv(v3d->uni_blend_proj, 1, GL_FALSE, mat);
+
+ glUniform3fv(v3d->uni_blend_fgcol, 1, fgcol);
+ glUniform3fv(v3d->uni_blend_bgcol, 1, bgcol);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, v3d->tex);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ if (v3d->supports_rowlen) {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ } else if (buf->stride == width) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
+ } else {
+ packed = malloc(width * height);
+ if (!packed)
+ return -ENOMEM;
+
+ src = buf->data;
+ dst = packed;
+ for (i = 0; i < height; ++i) {
+ memcpy(dst, src, width);
+ dst += width;
+ src += buf->stride;
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, packed);
+
+ free(packed);
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glUniform1i(v3d->uni_blend_tex, 0);
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
+
+ if (gl_has_error(v3d->blend_shader)) {
+ log_warning("GL error");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int uterm_drm3d_display_fake_blendv(struct uterm_display *disp,
+ const struct uterm_video_blend_req *req,
+ size_t num)
+{
+ int ret;
+ unsigned int i;
+
+ if (!disp || !req)
+ return -EINVAL;
+
+ for (i = 0; i < num; ++i, ++req) {
+ if (!req->buf)
+ continue;
+
+ ret = display_blend(disp, req->buf, req->x, req->y,
+ req->fr, req->fg, req->fb,
+ req->br, req->bg, req->bb);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int uterm_drm3d_display_fill(struct uterm_display *disp,
+ uint8_t r, uint8_t g, uint8_t b,
+ unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height)
+{
+ struct uterm_drm3d_video *v3d;
+ unsigned int sw, sh, tmp, i;
+ float mat[16];
+ float vertices[6 * 2], colors[6 * 4];
+ int ret;
+
+ v3d = uterm_drm_video_get_data(disp->video);
+ ret = uterm_drm3d_display_use(disp, NULL);
+ if (ret)
+ return ret;
+ ret = init_shaders(disp->video);
+ if (ret)
+ return ret;
+
+ sw = uterm_drm_mode_get_width(disp->current_mode);
+ sh = uterm_drm_mode_get_height(disp->current_mode);
+
+ for (i = 0; i < 6; ++i) {
+ colors[i * 4 + 0] = r / 255.0;
+ colors[i * 4 + 1] = g / 255.0;
+ colors[i * 4 + 2] = b / 255.0;
+ colors[i * 4 + 3] = 1.0;
+ }
+
+ vertices[0] = -1.0;
+ vertices[1] = -1.0;
+ vertices[2] = -1.0;
+ vertices[3] = +1.0;
+ vertices[4] = +1.0;
+ vertices[5] = +1.0;
+
+ vertices[6] = -1.0;
+ vertices[7] = -1.0;
+ vertices[8] = +1.0;
+ vertices[9] = +1.0;
+ vertices[10] = +1.0;
+ vertices[11] = -1.0;
+
+ tmp = x + width;
+ if (tmp < x || x >= sw)
+ return -EINVAL;
+ if (tmp > sw)
+ width = sw - x;
+ tmp = y + height;
+ if (tmp < y || y >= sh)
+ return -EINVAL;
+ if (tmp > sh)
+ height = sh - y;
+
+ glViewport(x, y, width, height);
+ glDisable(GL_BLEND);
+
+ gl_shader_use(v3d->fill_shader);
+ gl_m4_identity(mat);
+ glUniformMatrix4fv(v3d->uni_fill_proj, 1, GL_FALSE, mat);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
+
+ if (gl_has_error(v3d->fill_shader)) {
+ log_warning("GL error");
+ return -EFAULT;
+ }
+
+ return 0;
+}
diff --git a/src/uterm_video_drm.c b/src/uterm_drm3d_video.c
index 9e9590e..0ba9225 100644
--- a/src/uterm_video_drm.c
+++ b/src/uterm_drm3d_video.c
@@ -48,47 +48,11 @@
#include "log.h"
#include "static_gl.h"
#include "uterm_drm_shared_internal.h"
+#include "uterm_drm3d_internal.h"
#include "uterm_video.h"
#include "uterm_video_internal.h"
-#define LOG_SUBSYSTEM "video_drm"
-
-struct uterm_drm3d_rb {
- struct uterm_display *disp;
- struct gbm_bo *bo;
- uint32_t fb;
-};
-
-struct uterm_drm3d_display {
- struct gbm_surface *gbm;
- EGLSurface surface;
- struct uterm_drm3d_rb *current;
- struct uterm_drm3d_rb *next;
-};
-
-struct uterm_drm3d_video {
- struct gbm_device *gbm;
- EGLDisplay disp;
- EGLConfig conf;
- EGLContext ctx;
-
- unsigned int sinit;
- bool supports_rowlen;
- GLuint tex;
-
- struct gl_shader *fill_shader;
- GLuint uni_fill_proj;
-
- struct gl_shader *blend_shader;
- GLuint uni_blend_proj;
- GLuint uni_blend_tex;
- GLuint uni_blend_fgcol;
- GLuint uni_blend_bgcol;
-
- struct gl_shader *blit_shader;
- GLuint uni_blit_proj;
- GLuint uni_blit_tex;
-};
+#define LOG_SUBSYSTEM "uterm_drm3d_video"
static int display_init(struct uterm_display *disp)
{
@@ -305,7 +269,7 @@ static void display_deactivate(struct uterm_display *disp)
disp->current_mode = NULL;
}
-static int display_use(struct uterm_display *disp, bool *opengl)
+int uterm_drm3d_display_use(struct uterm_display *disp, bool *opengl)
{
struct uterm_drm3d_display *d3d = uterm_drm_display_get_data(disp);
struct uterm_drm3d_video *v3d;
@@ -376,458 +340,18 @@ static int display_swap(struct uterm_display *disp, bool immediate)
return 0;
}
-extern const char *gl_static_fill_vert;
-extern const char *gl_static_fill_frag;
-extern const char *gl_static_blend_vert;
-extern const char *gl_static_blend_frag;
-extern const char *gl_static_blit_vert;
-extern const char *gl_static_blit_frag;
-
-static int init_shaders(struct uterm_video *video)
-{
- struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
- int ret;
- char *fill_attr[] = { "position", "color" };
- char *blend_attr[] = { "position", "texture_position" };
- char *blit_attr[] = { "position", "texture_position" };
-
- if (v3d->sinit == 1)
- return -EFAULT;
- else if (v3d->sinit == 2)
- return 0;
-
- v3d->sinit = 1;
-
- ret = gl_shader_new(&v3d->fill_shader, gl_static_fill_vert,
- gl_static_fill_frag, fill_attr, 2, log_llog);
- if (ret)
- return ret;
-
- v3d->uni_fill_proj = gl_shader_get_uniform(v3d->fill_shader,
- "projection");
-
- ret = gl_shader_new(&v3d->blend_shader, gl_static_blend_vert,
- gl_static_blend_frag, blend_attr, 2, log_llog);
- if (ret)
- return ret;
-
- v3d->uni_blend_proj = gl_shader_get_uniform(v3d->blend_shader,
- "projection");
- v3d->uni_blend_tex = gl_shader_get_uniform(v3d->blend_shader,
- "texture");
- v3d->uni_blend_fgcol = gl_shader_get_uniform(v3d->blend_shader,
- "fgcolor");
- v3d->uni_blend_bgcol = gl_shader_get_uniform(v3d->blend_shader,
- "bgcolor");
-
- ret = gl_shader_new(&v3d->blit_shader, gl_static_blit_vert,
- gl_static_blit_frag, blit_attr, 2, log_llog);
- if (ret)
- return ret;
-
- v3d->uni_blit_proj = gl_shader_get_uniform(v3d->blit_shader,
- "projection");
- v3d->uni_blit_tex = gl_shader_get_uniform(v3d->blit_shader,
- "texture");
-
- gl_tex_new(&v3d->tex, 1);
- v3d->sinit = 2;
-
- return 0;
-}
-
-static void deinit_shaders(struct uterm_video *video)
-{
- struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
-
- if (v3d->sinit == 0)
- return;
-
- v3d->sinit = 0;
- gl_tex_free(&v3d->tex, 1);
- gl_shader_unref(v3d->blit_shader);
- gl_shader_unref(v3d->blend_shader);
- gl_shader_unref(v3d->fill_shader);
-}
-
-static int display_blit(struct uterm_display *disp,
- const struct uterm_video_buffer *buf,
- unsigned int x, unsigned int y)
-{
- struct uterm_drm3d_video *v3d;
- unsigned int sw, sh, tmp, width, height, i;
- float mat[16];
- float vertices[6 * 2], texpos[6 * 2];
- int ret;
- uint8_t *packed, *src, *dst;
-
- if (!buf || buf->format != UTERM_FORMAT_XRGB32)
- return -EINVAL;
-
- v3d = uterm_drm_video_get_data(disp->video);
- ret = display_use(disp, NULL);
- if (ret)
- return ret;
- ret = init_shaders(disp->video);
- if (ret)
- return ret;
-
- sw = uterm_drm_mode_get_width(disp->current_mode);
- sh = uterm_drm_mode_get_height(disp->current_mode);
-
- vertices[0] = -1.0;
- vertices[1] = -1.0;
- vertices[2] = -1.0;
- vertices[3] = +1.0;
- vertices[4] = +1.0;
- vertices[5] = +1.0;
-
- vertices[6] = -1.0;
- vertices[7] = -1.0;
- vertices[8] = +1.0;
- vertices[9] = +1.0;
- vertices[10] = +1.0;
- vertices[11] = -1.0;
-
- texpos[0] = 0.0;
- texpos[1] = 1.0;
- texpos[2] = 0.0;
- texpos[3] = 0.0;
- texpos[4] = 1.0;
- texpos[5] = 0.0;
-
- texpos[6] = 0.0;
- texpos[7] = 1.0;
- texpos[8] = 1.0;
- texpos[9] = 0.0;
- texpos[10] = 1.0;
- texpos[11] = 1.0;
-
- tmp = x + buf->width;
- if (tmp < x || x >= sw)
- return -EINVAL;
- if (tmp > sw)
- width = sw - x;
- else
- width = buf->width;
-
- tmp = y + buf->height;
- if (tmp < y || y >= sh)
- return -EINVAL;
- if (tmp > sh)
- height = sh - y;
- else
- height = buf->height;
-
- glViewport(x, sh - y - height, width, height);
- glDisable(GL_BLEND);
-
- gl_shader_use(v3d->blit_shader);
-
- gl_m4_identity(mat);
- glUniformMatrix4fv(v3d->uni_blit_proj, 1, GL_FALSE, mat);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, v3d->tex);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- if (v3d->supports_rowlen) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride / 4);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
- GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- } else if (buf->stride == width) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
- GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
- } else {
- packed = malloc(width * height);
- if (!packed)
- return -ENOMEM;
-
- src = buf->data;
- dst = packed;
- for (i = 0; i < height; ++i) {
- memcpy(dst, src, width * 4);
- dst += width * 4;
- src += buf->stride;
- }
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
- GL_BGRA_EXT, GL_UNSIGNED_BYTE, packed);
-
- free(packed);
- }
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glUniform1i(v3d->uni_blit_tex, 0);
-
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
-
- if (gl_has_error(v3d->blit_shader)) {
- log_warning("GL error");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int display_blend(struct uterm_display *disp,
- const struct uterm_video_buffer *buf,
- unsigned int x, unsigned int y,
- uint8_t fr, uint8_t fg, uint8_t fb,
- uint8_t br, uint8_t bg, uint8_t bb)
-{
- struct uterm_drm3d_video *v3d;
- unsigned int sw, sh, tmp, width, height, i;
- float mat[16];
- float vertices[6 * 2], texpos[6 * 2], fgcol[3], bgcol[3];
- int ret;
- uint8_t *packed, *src, *dst;
-
- if (!buf || buf->format != UTERM_FORMAT_GREY)
- return -EINVAL;
-
- v3d = uterm_drm_video_get_data(disp->video);
- ret = display_use(disp, NULL);
- if (ret)
- return ret;
- ret = init_shaders(disp->video);
- if (ret)
- return ret;
-
- sw = uterm_drm_mode_get_width(disp->current_mode);
- sh = uterm_drm_mode_get_height(disp->current_mode);
-
- vertices[0] = -1.0;
- vertices[1] = -1.0;
- vertices[2] = -1.0;
- vertices[3] = +1.0;
- vertices[4] = +1.0;
- vertices[5] = +1.0;
-
- vertices[6] = -1.0;
- vertices[7] = -1.0;
- vertices[8] = +1.0;
- vertices[9] = +1.0;
- vertices[10] = +1.0;
- vertices[11] = -1.0;
-
- texpos[0] = 0.0;
- texpos[1] = 1.0;
- texpos[2] = 0.0;
- texpos[3] = 0.0;
- texpos[4] = 1.0;
- texpos[5] = 0.0;
-
- texpos[6] = 0.0;
- texpos[7] = 1.0;
- texpos[8] = 1.0;
- texpos[9] = 0.0;
- texpos[10] = 1.0;
- texpos[11] = 1.0;
-
- fgcol[0] = fr / 255.0;
- fgcol[1] = fg / 255.0;
- fgcol[2] = fb / 255.0;
- bgcol[0] = br / 255.0;
- bgcol[1] = bg / 255.0;
- bgcol[2] = bb / 255.0;
-
- tmp = x + buf->width;
- if (tmp < x || x >= sw)
- return -EINVAL;
- if (tmp > sw)
- width = sw - x;
- else
- width = buf->width;
-
- tmp = y + buf->height;
- if (tmp < y || y >= sh)
- return -EINVAL;
- if (tmp > sh)
- height = sh - y;
- else
- height = buf->height;
-
- glViewport(x, sh - y - height, width, height);
- glDisable(GL_BLEND);
-
- gl_shader_use(v3d->blend_shader);
-
- gl_m4_identity(mat);
- glUniformMatrix4fv(v3d->uni_blend_proj, 1, GL_FALSE, mat);
-
- glUniform3fv(v3d->uni_blend_fgcol, 1, fgcol);
- glUniform3fv(v3d->uni_blend_bgcol, 1, bgcol);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, v3d->tex);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- if (v3d->supports_rowlen) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- } else if (buf->stride == width) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
- } else {
- packed = malloc(width * height);
- if (!packed)
- return -ENOMEM;
-
- src = buf->data;
- dst = packed;
- for (i = 0; i < height; ++i) {
- memcpy(dst, src, width);
- dst += width;
- src += buf->stride;
- }
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, packed);
-
- free(packed);
- }
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glUniform1i(v3d->uni_blend_tex, 0);
-
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
-
- if (gl_has_error(v3d->blend_shader)) {
- log_warning("GL error");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int display_fake_blendv(struct uterm_display *disp,
- const struct uterm_video_blend_req *req,
- size_t num)
-{
- int ret;
- unsigned int i;
-
- if (!disp || !req)
- return -EINVAL;
-
- for (i = 0; i < num; ++i, ++req) {
- if (!req->buf)
- continue;
-
- ret = display_blend(disp, req->buf, req->x, req->y,
- req->fr, req->fg, req->fb,
- req->br, req->bg, req->bb);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static int display_fill(struct uterm_display *disp,
- uint8_t r, uint8_t g, uint8_t b,
- unsigned int x, unsigned int y,
- unsigned int width, unsigned int height)
-{
- struct uterm_drm3d_video *v3d;
- unsigned int sw, sh, tmp, i;
- float mat[16];
- float vertices[6 * 2], colors[6 * 4];
- int ret;
-
- v3d = uterm_drm_video_get_data(disp->video);
- ret = display_use(disp, NULL);
- if (ret)
- return ret;
- ret = init_shaders(disp->video);
- if (ret)
- return ret;
-
- sw = uterm_drm_mode_get_width(disp->current_mode);
- sh = uterm_drm_mode_get_height(disp->current_mode);
-
- for (i = 0; i < 6; ++i) {
- colors[i * 4 + 0] = r / 255.0;
- colors[i * 4 + 1] = g / 255.0;
- colors[i * 4 + 2] = b / 255.0;
- colors[i * 4 + 3] = 1.0;
- }
-
- vertices[0] = -1.0;
- vertices[1] = -1.0;
- vertices[2] = -1.0;
- vertices[3] = +1.0;
- vertices[4] = +1.0;
- vertices[5] = +1.0;
-
- vertices[6] = -1.0;
- vertices[7] = -1.0;
- vertices[8] = +1.0;
- vertices[9] = +1.0;
- vertices[10] = +1.0;
- vertices[11] = -1.0;
-
- tmp = x + width;
- if (tmp < x || x >= sw)
- return -EINVAL;
- if (tmp > sw)
- width = sw - x;
- tmp = y + height;
- if (tmp < y || y >= sh)
- return -EINVAL;
- if (tmp > sh)
- height = sh - y;
-
- glViewport(x, y, width, height);
- glDisable(GL_BLEND);
-
- gl_shader_use(v3d->fill_shader);
- gl_m4_identity(mat);
- glUniformMatrix4fv(v3d->uni_fill_proj, 1, GL_FALSE, mat);
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
- glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
-
- if (gl_has_error(v3d->fill_shader)) {
- log_warning("GL error");
- return -EFAULT;
- }
-
- return 0;
-}
-
static const struct display_ops drm_display_ops = {
.init = display_init,
.destroy = display_destroy,
.activate = display_activate,
.deactivate = display_deactivate,
.set_dpms = uterm_drm_display_set_dpms,
- .use = display_use,
+ .use = uterm_drm3d_display_use,
.get_buffers = NULL,
.swap = display_swap,
- .blit = display_blit,
- .fake_blendv = display_fake_blendv,
- .fill = display_fill,
+ .blit = uterm_drm3d_display_blit,
+ .fake_blendv = uterm_drm3d_display_fake_blendv,
+ .fill = uterm_drm3d_display_fill,
};
static void show_displays(struct uterm_video *video)
@@ -847,7 +371,7 @@ static void show_displays(struct uterm_video *video)
if (iter->dpms != UTERM_DPMS_ON)
continue;
- ret = display_use(iter, NULL);
+ ret = uterm_drm3d_display_use(iter, NULL);
if (ret)
continue;
@@ -998,7 +522,7 @@ static void video_destroy(struct uterm_video *video)
if (!eglMakeCurrent(v3d->disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
v3d->ctx))
log_error("cannot activate GL context during destruction");
- deinit_shaders(video);
+ uterm_drm3d_deinit_shaders(video);
eglMakeCurrent(v3d->disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
@@ -1041,8 +565,8 @@ static const struct video_ops drm_video_ops = {
.wake_up = video_wake_up,
};
-static const struct uterm_video_module drm_module = {
+static const struct uterm_video_module drm3d_module = {
.ops = &drm_video_ops,
};
-const struct uterm_video_module *UTERM_VIDEO_DRM = &drm_module;
+const struct uterm_video_module *UTERM_VIDEO_DRM3D = &drm3d_module;
diff --git a/src/uterm_video.c b/src/uterm_video.c
index 259199c..6186bb2 100644
--- a/src/uterm_video.c
+++ b/src/uterm_video.c
@@ -64,7 +64,7 @@ bool uterm_video_available(const struct uterm_video_module *mod)
if (!mod)
return false;
- if (mod == UTERM_VIDEO_DRM2D || mod == UTERM_VIDEO_DRM)
+ if (mod == UTERM_VIDEO_DRM2D || mod == UTERM_VIDEO_DRM3D)
return video_drm_available();
return true;
diff --git a/src/uterm_video.h b/src/uterm_video.h
index 3aaff8b..4fe3845 100644
--- a/src/uterm_video.h
+++ b/src/uterm_video.h
@@ -220,10 +220,10 @@ extern const struct uterm_video_module *UTERM_VIDEO_DRM2D;
#define UTERM_VIDEO_DRM2D NULL
#endif
-#ifdef BUILD_ENABLE_VIDEO_DRM
-extern const struct uterm_video_module *UTERM_VIDEO_DRM;
+#ifdef BUILD_ENABLE_VIDEO_DRM3D
+extern const struct uterm_video_module *UTERM_VIDEO_DRM3D;
#else
-#define UTERM_VIDEO_DRM NULL
+#define UTERM_VIDEO_DRM3D NULL
#endif
#endif /* UTERM_UTERM_VIDEO_H */
diff --git a/src/uterm_video_internal.h b/src/uterm_video_internal.h
index 801316a..e2c9d95 100644
--- a/src/uterm_video_internal.h
+++ b/src/uterm_video_internal.h
@@ -180,7 +180,7 @@ static inline bool video_need_hotplug(const struct uterm_video *video)
.action = (act), \
})
-#if defined(BUILD_ENABLE_VIDEO_DRM) || defined(BUILD_ENABLE_VIDEO_DRM2D)
+#if defined(BUILD_ENABLE_VIDEO_DRM3D) || defined(BUILD_ENABLE_VIDEO_DRM2D)
#include <xf86drm.h>