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>
49 #include "static_gl.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 *gl_static_fill_vert;
58 extern const char *gl_static_fill_frag;
59 extern const char *gl_static_blend_vert;
60 extern const char *gl_static_blend_frag;
61 extern const char *gl_static_blit_vert;
62 extern const char *gl_static_blit_frag;
64 static int init_shaders(struct uterm_video *video)
66 struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
68 char *fill_attr[] = { "position", "color" };
69 char *blend_attr[] = { "position", "texture_position" };
70 char *blit_attr[] = { "position", "texture_position" };
74 else if (v3d->sinit == 2)
79 ret = gl_shader_new(&v3d->fill_shader, gl_static_fill_vert,
80 gl_static_fill_frag, fill_attr, 2, log_llog, NULL);
84 v3d->uni_fill_proj = gl_shader_get_uniform(v3d->fill_shader,
87 ret = gl_shader_new(&v3d->blend_shader, gl_static_blend_vert,
88 gl_static_blend_frag, blend_attr, 2, log_llog,
93 v3d->uni_blend_proj = gl_shader_get_uniform(v3d->blend_shader,
95 v3d->uni_blend_tex = gl_shader_get_uniform(v3d->blend_shader,
97 v3d->uni_blend_fgcol = gl_shader_get_uniform(v3d->blend_shader,
99 v3d->uni_blend_bgcol = gl_shader_get_uniform(v3d->blend_shader,
102 ret = gl_shader_new(&v3d->blit_shader, gl_static_blit_vert,
103 gl_static_blit_frag, blit_attr, 2, log_llog, NULL);
107 v3d->uni_blit_proj = gl_shader_get_uniform(v3d->blit_shader,
109 v3d->uni_blit_tex = gl_shader_get_uniform(v3d->blit_shader,
112 gl_tex_new(&v3d->tex, 1);
118 void uterm_drm3d_deinit_shaders(struct uterm_video *video)
120 struct uterm_drm3d_video *v3d = uterm_drm_video_get_data(video);
126 gl_tex_free(&v3d->tex, 1);
127 gl_shader_unref(v3d->blit_shader);
128 gl_shader_unref(v3d->blend_shader);
129 gl_shader_unref(v3d->fill_shader);
132 int uterm_drm3d_display_blit(struct uterm_display *disp,
133 const struct uterm_video_buffer *buf,
134 unsigned int x, unsigned int y)
136 struct uterm_drm3d_video *v3d;
137 unsigned int sw, sh, tmp, width, height, i;
139 float vertices[6 * 2], texpos[6 * 2];
141 uint8_t *packed, *src, *dst;
143 if (!buf || buf->format != UTERM_FORMAT_XRGB32)
146 v3d = uterm_drm_video_get_data(disp->video);
147 ret = uterm_drm3d_display_use(disp, NULL);
150 ret = init_shaders(disp->video);
154 sw = uterm_drm_mode_get_width(disp->current_mode);
155 sh = uterm_drm_mode_get_height(disp->current_mode);
185 tmp = x + buf->width;
186 if (tmp < x || x >= sw)
193 tmp = y + buf->height;
194 if (tmp < y || y >= sh)
199 height = buf->height;
201 glViewport(x, sh - y - height, width, height);
204 gl_shader_use(v3d->blit_shader);
207 glUniformMatrix4fv(v3d->uni_blit_proj, 1, GL_FALSE, mat);
209 glActiveTexture(GL_TEXTURE0);
210 glBindTexture(GL_TEXTURE_2D, v3d->tex);
211 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
213 if (v3d->supports_rowlen) {
214 glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride / 4);
215 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
216 GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
217 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
218 } else if (buf->stride == width) {
219 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
220 GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data);
222 packed = malloc(width * height);
228 for (i = 0; i < height; ++i) {
229 memcpy(dst, src, width * 4);
234 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
235 GL_BGRA_EXT, GL_UNSIGNED_BYTE, packed);
240 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
241 glUniform1i(v3d->uni_blit_tex, 0);
243 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
244 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
245 glEnableVertexAttribArray(0);
246 glEnableVertexAttribArray(1);
247 glDrawArrays(GL_TRIANGLES, 0, 6);
248 glDisableVertexAttribArray(0);
249 glDisableVertexAttribArray(1);
251 if (gl_has_error(v3d->blit_shader)) {
252 log_warning("GL error");
259 static int display_blend(struct uterm_display *disp,
260 const struct uterm_video_buffer *buf,
261 unsigned int x, unsigned int y,
262 uint8_t fr, uint8_t fg, uint8_t fb,
263 uint8_t br, uint8_t bg, uint8_t bb)
265 struct uterm_drm3d_video *v3d;
266 unsigned int sw, sh, tmp, width, height, i;
268 float vertices[6 * 2], texpos[6 * 2], fgcol[3], bgcol[3];
270 uint8_t *packed, *src, *dst;
272 if (!buf || buf->format != UTERM_FORMAT_GREY)
275 v3d = uterm_drm_video_get_data(disp->video);
276 ret = uterm_drm3d_display_use(disp, NULL);
279 ret = init_shaders(disp->video);
283 sw = uterm_drm_mode_get_width(disp->current_mode);
284 sh = uterm_drm_mode_get_height(disp->current_mode);
314 fgcol[0] = fr / 255.0;
315 fgcol[1] = fg / 255.0;
316 fgcol[2] = fb / 255.0;
317 bgcol[0] = br / 255.0;
318 bgcol[1] = bg / 255.0;
319 bgcol[2] = bb / 255.0;
321 tmp = x + buf->width;
322 if (tmp < x || x >= sw)
329 tmp = y + buf->height;
330 if (tmp < y || y >= sh)
335 height = buf->height;
337 glViewport(x, sh - y - height, width, height);
340 gl_shader_use(v3d->blend_shader);
343 glUniformMatrix4fv(v3d->uni_blend_proj, 1, GL_FALSE, mat);
345 glUniform3fv(v3d->uni_blend_fgcol, 1, fgcol);
346 glUniform3fv(v3d->uni_blend_bgcol, 1, bgcol);
348 glActiveTexture(GL_TEXTURE0);
349 glBindTexture(GL_TEXTURE_2D, v3d->tex);
350 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
352 if (v3d->supports_rowlen) {
353 glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride);
354 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
355 GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
356 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
357 } else if (buf->stride == width) {
358 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
359 GL_ALPHA, GL_UNSIGNED_BYTE, buf->data);
361 packed = malloc(width * height);
367 for (i = 0; i < height; ++i) {
368 memcpy(dst, src, width);
373 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
374 GL_ALPHA, GL_UNSIGNED_BYTE, packed);
379 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
380 glUniform1i(v3d->uni_blend_tex, 0);
382 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
383 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos);
384 glEnableVertexAttribArray(0);
385 glEnableVertexAttribArray(1);
386 glDrawArrays(GL_TRIANGLES, 0, 6);
387 glDisableVertexAttribArray(0);
388 glDisableVertexAttribArray(1);
390 if (gl_has_error(v3d->blend_shader)) {
391 log_warning("GL error");
398 int uterm_drm3d_display_fake_blendv(struct uterm_display *disp,
399 const struct uterm_video_blend_req *req,
408 for (i = 0; i < num; ++i, ++req) {
412 ret = display_blend(disp, req->buf, req->x, req->y,
413 req->fr, req->fg, req->fb,
414 req->br, req->bg, req->bb);
422 int uterm_drm3d_display_fill(struct uterm_display *disp,
423 uint8_t r, uint8_t g, uint8_t b,
424 unsigned int x, unsigned int y,
425 unsigned int width, unsigned int height)
427 struct uterm_drm3d_video *v3d;
428 unsigned int sw, sh, tmp, i;
430 float vertices[6 * 2], colors[6 * 4];
433 v3d = uterm_drm_video_get_data(disp->video);
434 ret = uterm_drm3d_display_use(disp, NULL);
437 ret = init_shaders(disp->video);
441 sw = uterm_drm_mode_get_width(disp->current_mode);
442 sh = uterm_drm_mode_get_height(disp->current_mode);
444 for (i = 0; i < 6; ++i) {
445 colors[i * 4 + 0] = r / 255.0;
446 colors[i * 4 + 1] = g / 255.0;
447 colors[i * 4 + 2] = b / 255.0;
448 colors[i * 4 + 3] = 1.0;
466 if (tmp < x || x >= sw)
471 if (tmp < y || y >= sh)
476 glViewport(x, y, width, height);
479 gl_shader_use(v3d->fill_shader);
481 glUniformMatrix4fv(v3d->uni_fill_proj, 1, GL_FALSE, mat);
482 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
483 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
484 glEnableVertexAttribArray(0);
485 glEnableVertexAttribArray(1);
486 glDrawArrays(GL_TRIANGLES, 0, 6);
487 glDisableVertexAttribArray(0);
488 glDisableVertexAttribArray(1);
490 if (gl_has_error(v3d->fill_shader)) {
491 log_warning("GL error");