console: use new drawing pipeline

Instead of drawing with fixed-function GL pipeline we now use our own
shader for texture drawing. This also fixes test_console to no longer
depend on GL.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-01-20 15:45:58 +01:00
parent 84f29458e5
commit 83cec439c6
5 changed files with 87 additions and 50 deletions

View File

@ -85,12 +85,7 @@ kmscon_SOURCES = src/main.c
kmscon_LDADD = libkmscon-core.la
test_console_SOURCES = tests/test_console.c
test_console_LDADD = \
libkmscon-core.la \
$(OPENGL_LIBS)
test_console_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(OPENGL_CFLAGS)
test_console_LDADD = libkmscon-core.la
test_output_SOURCES = tests/test_output.c
test_output_LDADD = libkmscon-core.la

View File

@ -31,20 +31,12 @@
* to a framebuffer as used by terminals and consoles.
*/
/*
* TODO: Avoid using this hack and instead retrieve GL extension
* pointers dynamically on initialization.
*/
#define GL_GLEXT_PROTOTYPES
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <cairo.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "console.h"
#include "font.h"
@ -56,9 +48,10 @@ struct kmscon_console {
size_t ref;
struct kmscon_font_factory *ff;
struct kmscon_compositor *comp;
struct kmscon_context *ctx;
/* GL texture and font */
GLuint tex;
unsigned int tex;
unsigned int res_x;
unsigned int res_y;
struct kmscon_font *font;
@ -81,7 +74,7 @@ struct kmscon_console {
static void kmscon_console_free_res(struct kmscon_console *con)
{
if (con && con->cr) {
glDeleteTextures(1, &con->tex);
kmscon_context_free_tex(con->ctx, con->tex);
cairo_destroy(con->cr);
cairo_surface_destroy(con->surf);
free(con->surf_buf);
@ -128,11 +121,7 @@ static int kmscon_console_new_res(struct kmscon_console *con)
con->surf = surface;
con->cr = cr;
glGenTextures(1, &con->tex);
glBindTexture(GL_TEXTURE_RECTANGLE, con->tex);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, con->res_x, con->res_y,
0, GL_BGRA, GL_UNSIGNED_BYTE, con->surf_buf);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
con->tex = kmscon_context_new_tex(con->ctx);
log_debug("console: new resolution %ux%u\n", con->res_x, con->res_y);
return 0;
@ -162,6 +151,7 @@ int kmscon_console_new(struct kmscon_console **out,
con->ref = 1;
con->ff = ff;
con->comp = comp;
con->ctx = kmscon_compositor_get_context(comp);
log_debug("console: new console\n");
ret = kmscon_buffer_new(&con->cells, 0, 0);
@ -328,9 +318,8 @@ void kmscon_console_draw(struct kmscon_console *con)
cairo_restore(con->cr);
/* refresh GL texture contents */
glBindTexture(GL_TEXTURE_RECTANGLE, con->tex);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, con->res_x, con->res_y,
0, GL_BGRA, GL_UNSIGNED_BYTE, con->surf_buf);
kmscon_context_set_tex(con->ctx, con->tex, con->res_x, con->res_y,
con->surf_buf);
}
/*
@ -345,29 +334,13 @@ void kmscon_console_draw(struct kmscon_console *con)
*/
void kmscon_console_map(struct kmscon_console *con)
{
static const float vertices[] = { -1, -1, 1, -1, 1, 1, -1, 1 };
static const float texpos[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
if (!con || !con->cr)
return;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_RECTANGLE);
glBindTexture(GL_TEXTURE_RECTANGLE, con->tex);
glBegin(GL_QUADS);
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(con->res_x, 0.0f);
glVertex2f(1.0f, -1.0f);
glTexCoord2f(con->res_x, con->res_y);
glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, con->res_y);
glVertex2f(-1.0f, 1.0f);
glEnd();
kmscon_context_draw_tex(con->ctx, vertices, texpos, 4, con->tex);
}
void kmscon_console_write(struct kmscon_console *con, kmscon_symbol_t ch)

View File

@ -121,6 +121,12 @@ void kmscon_context_viewport(struct kmscon_context *ctx,
void kmscon_context_clear(struct kmscon_context *ctx);
void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices,
float *colors, size_t num);
void kmscon_context_draw_tex(struct kmscon_context *ctx, const float *vertices,
const float *texcoords, size_t num, unsigned int tex);
unsigned int kmscon_context_new_tex(struct kmscon_context *ctx);
void kmscon_context_free_tex(struct kmscon_context *ctx, unsigned int tex);
void kmscon_context_set_tex(struct kmscon_context *ctx, unsigned int tex,
unsigned int width, unsigned int height, void *buf);
/* compositors */

View File

@ -86,6 +86,7 @@ typedef GLint (*PFNGLGETUNIFORMLOCATIONPROC)
(GLuint program, const GLchar *name);
typedef void (*PFNGLUNIFORMMATRIX4FVPROC) (GLint location,
GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
typedef void (*PFNGLVERTEXATTRIBPOINTERPROC)
(GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, const GLvoid *pointer);
@ -139,6 +140,7 @@ struct kmscon_context {
PFNGLGETPROGRAMINFOLOGPROC proc_get_program_info_log;
PFNGLGETUNIFORMLOCATIONPROC proc_get_uniform_location;
PFNGLUNIFORMMATRIX4FVPROC proc_uniform_matrix_4fv;
PFNGLUNIFORM1IPROC proc_uniform_1i;
PFNGLVERTEXATTRIBPOINTERPROC proc_vertex_attrib_pointer;
PFNGLENABLEVERTEXATTRIBARRAYPROC proc_enable_vertex_attrib_array;
PFNGLDRAWARRAYSEXTPROC proc_draw_arrays;
@ -423,6 +425,8 @@ int kmscon_context_new(struct kmscon_context **out, void *gbm)
(void*) eglGetProcAddress("glGetUniformLocation");
ctx->proc_uniform_matrix_4fv =
(void*) eglGetProcAddress("glUniformMatrix4fv");
ctx->proc_uniform_1i =
(void*) eglGetProcAddress("glUniform1i");
ctx->proc_vertex_attrib_pointer =
(void*) eglGetProcAddress("glVertexAttribPointer");
ctx->proc_enable_vertex_attrib_array =
@ -462,6 +466,7 @@ int kmscon_context_new(struct kmscon_context **out, void *gbm)
!ctx->proc_get_program_info_log ||
!ctx->proc_get_uniform_location ||
!ctx->proc_uniform_matrix_4fv ||
!ctx->proc_uniform_1i ||
!ctx->proc_vertex_attrib_pointer ||
!ctx->proc_enable_vertex_attrib_array ||
!ctx->proc_draw_arrays) {
@ -612,6 +617,67 @@ void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices,
ctx->proc_draw_arrays(GL_QUADS, 0, num);
}
void kmscon_context_draw_tex(struct kmscon_context *ctx, const float *vertices,
const float *texcoords, size_t num, unsigned int tex)
{
static const float m[16] = { 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
if (!ctx)
return;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
ctx->proc_use_program(ctx->tex_program);
ctx->proc_uniform_matrix_4fv(ctx->tex_uni_projection, 1, GL_FALSE, m);
ctx->proc_uniform_1i(ctx->tex_uni_texture, 0);
ctx->proc_vertex_attrib_pointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
ctx->proc_vertex_attrib_pointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
ctx->proc_enable_vertex_attrib_array(0);
ctx->proc_enable_vertex_attrib_array(1);
ctx->proc_draw_arrays(GL_QUADS, 0, num);
}
unsigned int kmscon_context_new_tex(struct kmscon_context *ctx)
{
GLuint tex = 0;
if (!ctx)
return tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return tex;
}
void kmscon_context_free_tex(struct kmscon_context *ctx, unsigned int tex)
{
if (!ctx)
return;
glDeleteTextures(1, &tex);
}
void kmscon_context_set_tex(struct kmscon_context *ctx, unsigned int tex,
unsigned int width, unsigned int height, void *buf)
{
if (!ctx || !buf || !width || !height)
return;
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA,
GL_UNSIGNED_BYTE, buf);
}
int renderbuffer_new(struct renderbuffer **out, struct kmscon_context *ctx,
void *bo)
{

View File

@ -40,7 +40,6 @@
*/
#define _BSD_SOURCE
#define GL_GLEXT_PROTOTYPES
#include <errno.h>
#include <inttypes.h>
@ -51,8 +50,6 @@
#include <string.h>
#include <unistd.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "console.h"
#include "eloop.h"
#include "font.h"
@ -116,11 +113,13 @@ static void map_outputs(struct console *con)
{
int ret;
struct kmscon_output *iter;
struct kmscon_context *ctx;
if (kmscon_compositor_is_asleep(con->comp))
return;
kmscon_console_draw(con->con);
ctx = kmscon_compositor_get_context(con->comp);
iter = kmscon_compositor_get_outputs(con->comp);
for ( ; iter; iter = kmscon_output_next(iter)) {
@ -131,9 +130,7 @@ static void map_outputs(struct console *con)
if (ret)
continue;
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
kmscon_context_clear(ctx);
kmscon_console_map(con->con);
ret = kmscon_output_swap(iter);