int gl_m4_stack_new(struct gl_m4_stack **out) { struct gl_m4_stack *stack; if (!out) return -EINVAL; stack = malloc(sizeof(*stack)); if (!stack) return -ENOMEM; memset(stack, 0, sizeof(*stack)); gl_m4_identity(stack->stack.matrix); *out = stack; return 0; }
float *gl_m4_stack_pop(struct gl_m4_stack *stack) { struct gl_m4_entry *entry; if (!stack) return NULL; entry = stack->stack.next; if (!entry) { gl_m4_identity(stack->stack.matrix); return stack->stack.matrix; } stack->stack.next = entry->next; entry->next = stack->cache; stack->cache = entry; gl_m4_copy(stack->stack.matrix, entry->matrix); return stack->stack.matrix; }
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; /* Caution: * opengl uses a coordinate system with the origin at _lower-left_ corner * and positive y-axis up, while other parts uses a coordinate system * with the origin at _upper-left_ corner and positive y-axis down. */ y = sh - y; // invert y-axis y -= height; // move origin to lower left corner 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 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; }
static void kmscon_buffer_draw(struct kmscon_buffer *buf, struct font_screen *fscr) { unsigned int i, j, k, num; struct line *iter, *line = NULL; struct cell *cell; int idx; float m[16]; if (!buf || !fscr) return; font_screen_draw_start(fscr); iter = buf->position; k = 0; idx = 0; for (i = 0; i < buf->size_y; ++i) { if (iter) { line = iter; iter = iter->next; } else { if (idx == 0) { if (k < buf->mtop_y) { line = buf->mtop_buf[k]; } else { k = 0; idx = 1; } } if (idx == 1) { if (k < buf->scroll_y) { line = buf->scroll_buf[k]; } else { k = 0; idx = 2; } } if (idx == 2) { if (k < buf->mbottom_y) line = buf->mbottom_buf[k]; else break; } k++; } if (!line) continue; if (line->size < buf->size_x) num = line->size; else num = buf->size_x; for (j = 0; j < num; ++j) { cell = &line->cells[j]; font_screen_draw_char(fscr, cell->ch, j, i, 1, 1); } } gl_m4_identity(m); font_screen_draw_perform(fscr, m); }