2 * uterm - Linux User-Space Terminal
4 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #define EGL_EGLEXT_PROTOTYPES
31 #define GL_GLEXT_PROTOTYPES
34 #include <EGL/eglext.h>
38 #include <GLES2/gl2.h>
39 #include <GLES2/gl2ext.h>
46 #include <xf86drmMode.h>
50 #include "uterm_drm_shared_internal.h"
51 #include "uterm_drm3d_internal.h"
52 #include "uterm_video.h"
53 #include "uterm_video_internal.h"
55 #define LOG_SUBSYSTEM "uterm_drm3d_render"
57 extern const char _binary_src_uterm_drm3d_blend_vert_bin_start[];
58 extern const char _binary_src_uterm_drm3d_blend_vert_bin_end[];
59 extern const char _binary_src_uterm_drm3d_blend_frag_bin_start[];
60 extern const char _binary_src_uterm_drm3d_blend_frag_bin_end[];
61 extern const char _binary_src_uterm_drm3d_blit_vert_bin_start[];
62 extern const char _binary_src_uterm_drm3d_blit_vert_bin_end[];
63 extern const char _binary_src_uterm_drm3d_blit_frag_bin_start[];
64 extern const char _binary_src_uterm_drm3d_blit_frag_bin_end[];
65 extern const char _binary_src_uterm_drm3d_fill_vert_bin_start[];
66 extern const char _binary_src_uterm_drm3d_fill_vert_bin_end[];
67 extern const char _binary_src_uterm_drm3d_fill_frag_bin_start[];
68 extern const char _binary_src_uterm_drm3d_fill_frag_bin_end[];
70 static int init_shaders(struct uterm_video *video)
72 struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
74 char *fill_attr[] = { "position", "color" };
75 char *blend_attr[] = { "position", "texture_position" };
76 char *blit_attr[] = { "position", "texture_position" };
77 int blend_vlen, blend_flen, blit_vlen, blit_flen, fill_vlen, fill_flen;
78 const char *blend_vert, *blend_frag;
79 const char *blit_vert, *blit_frag;
80 const char *fill_vert, *fill_frag;
84 else if (v3d->sinit == 2)
89 blend_vert = _binary_src_uterm_drm3d_blend_vert_bin_start;
90 blend_vlen = _binary_src_uterm_drm3d_blend_vert_bin_end - blend_vert;
91 blend_frag = _binary_src_uterm_drm3d_blend_frag_bin_start;
92 blend_flen = _binary_src_uterm_drm3d_blend_frag_bin_end - blend_frag;
93 blit_vert = _binary_src_uterm_drm3d_blit_vert_bin_start;
94 blit_vlen = _binary_src_uterm_drm3d_blit_vert_bin_end - blit_vert;
95 blit_frag = _binary_src_uterm_drm3d_blit_frag_bin_start;
96 blit_flen = _binary_src_uterm_drm3d_blit_frag_bin_end - blit_frag;
97 fill_vert = _binary_src_uterm_drm3d_fill_vert_bin_start;
98 fill_vlen = _binary_src_uterm_drm3d_fill_vert_bin_end - fill_vert;
99 fill_frag = _binary_src_uterm_drm3d_fill_frag_bin_start;
100 fill_flen = _binary_src_uterm_drm3d_fill_frag_bin_end - fill_frag;
102 ret = gl_shader_new(&v3d->fill_shader, fill_vert, fill_vlen,
103 fill_frag, fill_flen, fill_attr, 2, log_llog,
108 v3d->uni_fill_proj = gl_shader_get_uniform(v3d->fill_shader,
111 ret = gl_shader_new(&v3d->blend_shader, blend_vert, blend_vlen,
112 blend_frag, blend_flen, blend_attr, 2, log_llog,
117 v3d->uni_blend_proj = gl_shader_get_uniform(v3d->blend_shader,
119 v3d->uni_blend_tex = gl_shader_get_uniform(v3d->blend_shader,
121 v3d->uni_blend_fgcol = gl_shader_get_uniform(v3d->blend_shader,
123 v3d->uni_blend_bgcol = gl_shader_get_uniform(v3d->blend_shader,
126 ret = gl_shader_new(&v3d->blit_shader, blit_vert, blit_vlen,
127 blit_frag, blit_flen, blit_attr, 2, log_llog,
132 v3d->uni_blit_proj = gl_shader_get_uniform(v3d->blit_shader,
134 v3d->uni_blit_tex = gl_shader_get_uniform(v3d->blit_shader,
137 gl_tex_new(&v3d->tex, 1);
143 void uterm_drm3d_deinit_shaders(struct uterm_video *video)
145 struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
151 gl_tex_free(&v3d->tex, 1);
152 gl_shader_unref(v3d->blit_shader);
153 gl_shader_unref(v3d->blend_shader);
154 gl_shader_unref(v3d->fill_shader);
157 int uterm_drm3d_display_blit(struct uterm_display *disp,
158 const struct uterm_video_buffer *buf,
159 unsigned int x, unsigned int y)
161 struct uterm_drm3d_video *v3d;
162 unsigned int sw, sh, tmp, width, height, i;
164 float vertices[6 * 2], texpos[6 * 2];
166 uint8_t *packed, *src, *dst;
168 if (!buf || buf->format != UTERM_FORMAT_XRGB32)
171 v3d = uterm_drm_video_get_data(disp->video);
172 ret = uterm_drm3d_display_use(disp, NULL);
175 ret = init_shaders(disp->video);
179 sw = uterm_drm_mode_get_width(disp->current_mode);
180 sh = uterm_drm_mode_get_height(disp->current_mode);
210 tmp = x + buf->width;
211 if (tmp < x || x >= sw)
218 tmp = y + buf->height;
219 if (tmp < y || y >= sh)
224 height = buf->height;
226 glViewport(x, sh - y - height, width, height);
229 gl_shader_use(v3d->blit_shader);
232 glUniformMatrix4fv(v3d->uni_blit_proj, 1, GL_FALSE, mat);
234 glActiveTexture(GL_TEXTURE0);
235 glBindTexture(GL_TEXTURE_2D, v3d->tex);
236 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
238 if (v3d->supports_rowlen) {
239 glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride / 4);
240 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
241 GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
242 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
243 } else if (buf->stride == width) {
244 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
245 GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
247 packed = malloc(width * height);
253 for (i = 0; i < height; ++i) {
254 memcpy(dst, src, width * 4);
259 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
260 GL_BGRA_EXT, GL_UNSIGNED_BYTE, packed);
265 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
266 glUniform1i(v3d->uni_blit_tex, 0);
268 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
269 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
270 glEnableVertexAttribArray(0);
271 glEnableVertexAttribArray(1);
272 glDrawArrays(GL_TRIANGLES, 0, 6);
273 glDisableVertexAttribArray(0);
274 glDisableVertexAttribArray(1);
276 if (gl_has_error(v3d->blit_shader)) {
277 log_warning("GL error");
284 static int display_blend(struct uterm_display *disp,
285 const struct uterm_video_buffer *buf,
286 unsigned int x, unsigned int y,
287 uint8_t fr, uint8_t fg, uint8_t fb,
288 uint8_t br, uint8_t bg, uint8_t bb)
290 struct uterm_drm3d_video *v3d;
291 unsigned int sw, sh, tmp, width, height, i;
293 float vertices[6 * 2], texpos[6 * 2], fgcol[3], bgcol[3];
295 uint8_t *packed, *src, *dst;
297 if (!buf || buf->format != UTERM_FORMAT_GREY)
300 v3d = uterm_drm_video_get_data(disp->video);
301 ret = uterm_drm3d_display_use(disp, NULL);
304 ret = init_shaders(disp->video);
308 sw = uterm_drm_mode_get_width(disp->current_mode);
309 sh = uterm_drm_mode_get_height(disp->current_mode);
339 fgcol[0] = fr / 255.0;
340 fgcol[1] = fg / 255.0;
341 fgcol[2] = fb / 255.0;
342 bgcol[0] = br / 255.0;
343 bgcol[1] = bg / 255.0;
344 bgcol[2] = bb / 255.0;
346 tmp = x + buf->width;
347 if (tmp < x || x >= sw)
354 tmp = y + buf->height;
355 if (tmp < y || y >= sh)
360 height = buf->height;
362 glViewport(x, sh - y - height, width, height);
365 gl_shader_use(v3d->blend_shader);
368 glUniformMatrix4fv(v3d->uni_blend_proj, 1, GL_FALSE, mat);
370 glUniform3fv(v3d->uni_blend_fgcol, 1, fgcol);
371 glUniform3fv(v3d->uni_blend_bgcol, 1, bgcol);
373 glActiveTexture(GL_TEXTURE0);
374 glBindTexture(GL_TEXTURE_2D, v3d->tex);
375 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
377 if (v3d->supports_rowlen) {
378 glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride);
379 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
380 GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
381 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
382 } else if (buf->stride == width) {
383 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
384 GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
386 packed = malloc(width * height);
392 for (i = 0; i < height; ++i) {
393 memcpy(dst, src, width);
398 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
399 GL_ALPHA, GL_UNSIGNED_BYTE, packed);
404 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
405 glUniform1i(v3d->uni_blend_tex, 0);
407 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
408 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
409 glEnableVertexAttribArray(0);
410 glEnableVertexAttribArray(1);
411 glDrawArrays(GL_TRIANGLES, 0, 6);
412 glDisableVertexAttribArray(0);
413 glDisableVertexAttribArray(1);
415 if (gl_has_error(v3d->blend_shader)) {
416 log_warning("GL error");
423 int uterm_drm3d_display_fake_blendv(struct uterm_display *disp,
424 const struct uterm_video_blend_req *req,
433 for (i = 0; i < num; ++i, ++req) {
437 ret = display_blend(disp, req->buf, req->x, req->y,
438 req->fr, req->fg, req->fb,
439 req->br, req->bg, req->bb);
447 int uterm_drm3d_display_fill(struct uterm_display *disp,
448 uint8_t r, uint8_t g, uint8_t b,
449 unsigned int x, unsigned int y,
450 unsigned int width, unsigned int height)
452 struct uterm_drm3d_video *v3d;
453 unsigned int sw, sh, tmp, i;
455 float vertices[6 * 2], colors[6 * 4];
458 v3d = uterm_drm_video_get_data(disp->video);
459 ret = uterm_drm3d_display_use(disp, NULL);
462 ret = init_shaders(disp->video);
466 sw = uterm_drm_mode_get_width(disp->current_mode);
467 sh = uterm_drm_mode_get_height(disp->current_mode);
469 for (i = 0; i < 6; ++i) {
470 colors[i * 4 + 0] = r / 255.0;
471 colors[i * 4 + 1] = g / 255.0;
472 colors[i * 4 + 2] = b / 255.0;
473 colors[i * 4 + 3] = 1.0;
491 if (tmp < x || x >= sw)
496 if (tmp < y || y >= sh)
501 glViewport(x, y, width, height);
504 gl_shader_use(v3d->fill_shader);
506 glUniformMatrix4fv(v3d->uni_fill_proj, 1, GL_FALSE, mat);
507 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
508 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
509 glEnableVertexAttribArray(0);
510 glEnableVertexAttribArray(1);
511 glDrawArrays(GL_TRIANGLES, 0, 6);
512 glDisableVertexAttribArray(0);
513 glDisableVertexAttribArray(1);
515 if (gl_has_error(v3d->fill_shader)) {
516 log_warning("GL error");