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 kmscon_LDADD = libkmscon-core.la
test_console_SOURCES = tests/test_console.c test_console_SOURCES = tests/test_console.c
test_console_LDADD = \ test_console_LDADD = libkmscon-core.la
libkmscon-core.la \
$(OPENGL_LIBS)
test_console_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(OPENGL_CFLAGS)
test_output_SOURCES = tests/test_output.c test_output_SOURCES = tests/test_output.c
test_output_LDADD = libkmscon-core.la test_output_LDADD = libkmscon-core.la

View File

@ -31,20 +31,12 @@
* to a framebuffer as used by terminals and consoles. * 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 <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <cairo.h> #include <cairo.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "console.h" #include "console.h"
#include "font.h" #include "font.h"
@ -56,9 +48,10 @@ struct kmscon_console {
size_t ref; size_t ref;
struct kmscon_font_factory *ff; struct kmscon_font_factory *ff;
struct kmscon_compositor *comp; struct kmscon_compositor *comp;
struct kmscon_context *ctx;
/* GL texture and font */ /* GL texture and font */
GLuint tex; unsigned int tex;
unsigned int res_x; unsigned int res_x;
unsigned int res_y; unsigned int res_y;
struct kmscon_font *font; struct kmscon_font *font;
@ -81,7 +74,7 @@ struct kmscon_console {
static void kmscon_console_free_res(struct kmscon_console *con) static void kmscon_console_free_res(struct kmscon_console *con)
{ {
if (con && con->cr) { if (con && con->cr) {
glDeleteTextures(1, &con->tex); kmscon_context_free_tex(con->ctx, con->tex);
cairo_destroy(con->cr); cairo_destroy(con->cr);
cairo_surface_destroy(con->surf); cairo_surface_destroy(con->surf);
free(con->surf_buf); free(con->surf_buf);
@ -128,11 +121,7 @@ static int kmscon_console_new_res(struct kmscon_console *con)
con->surf = surface; con->surf = surface;
con->cr = cr; con->cr = cr;
glGenTextures(1, &con->tex); con->tex = kmscon_context_new_tex(con->ctx);
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);
log_debug("console: new resolution %ux%u\n", con->res_x, con->res_y); log_debug("console: new resolution %ux%u\n", con->res_x, con->res_y);
return 0; return 0;
@ -162,6 +151,7 @@ int kmscon_console_new(struct kmscon_console **out,
con->ref = 1; con->ref = 1;
con->ff = ff; con->ff = ff;
con->comp = comp; con->comp = comp;
con->ctx = kmscon_compositor_get_context(comp);
log_debug("console: new console\n"); log_debug("console: new console\n");
ret = kmscon_buffer_new(&con->cells, 0, 0); ret = kmscon_buffer_new(&con->cells, 0, 0);
@ -328,9 +318,8 @@ void kmscon_console_draw(struct kmscon_console *con)
cairo_restore(con->cr); cairo_restore(con->cr);
/* refresh GL texture contents */ /* refresh GL texture contents */
glBindTexture(GL_TEXTURE_RECTANGLE, con->tex); kmscon_context_set_tex(con->ctx, con->tex, con->res_x, con->res_y,
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, con->res_x, con->res_y, con->surf_buf);
0, GL_BGRA, GL_UNSIGNED_BYTE, con->surf_buf);
} }
/* /*
@ -345,29 +334,13 @@ void kmscon_console_draw(struct kmscon_console *con)
*/ */
void kmscon_console_map(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) if (!con || !con->cr)
return; return;
glEnable(GL_BLEND); kmscon_context_draw_tex(con->ctx, vertices, texpos, 4, con->tex);
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();
} }
void kmscon_console_write(struct kmscon_console *con, kmscon_symbol_t ch) 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_clear(struct kmscon_context *ctx);
void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices, void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices,
float *colors, size_t num); 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 */ /* compositors */

View File

@ -86,6 +86,7 @@ typedef GLint (*PFNGLGETUNIFORMLOCATIONPROC)
(GLuint program, const GLchar *name); (GLuint program, const GLchar *name);
typedef void (*PFNGLUNIFORMMATRIX4FVPROC) (GLint location, typedef void (*PFNGLUNIFORMMATRIX4FVPROC) (GLint location,
GLsizei count, GLboolean transpose, const GLfloat *value); GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (*PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
typedef void (*PFNGLVERTEXATTRIBPOINTERPROC) typedef void (*PFNGLVERTEXATTRIBPOINTERPROC)
(GLuint index, GLint size, GLenum type, GLboolean normalized, (GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, const GLvoid *pointer); GLsizei stride, const GLvoid *pointer);
@ -139,6 +140,7 @@ struct kmscon_context {
PFNGLGETPROGRAMINFOLOGPROC proc_get_program_info_log; PFNGLGETPROGRAMINFOLOGPROC proc_get_program_info_log;
PFNGLGETUNIFORMLOCATIONPROC proc_get_uniform_location; PFNGLGETUNIFORMLOCATIONPROC proc_get_uniform_location;
PFNGLUNIFORMMATRIX4FVPROC proc_uniform_matrix_4fv; PFNGLUNIFORMMATRIX4FVPROC proc_uniform_matrix_4fv;
PFNGLUNIFORM1IPROC proc_uniform_1i;
PFNGLVERTEXATTRIBPOINTERPROC proc_vertex_attrib_pointer; PFNGLVERTEXATTRIBPOINTERPROC proc_vertex_attrib_pointer;
PFNGLENABLEVERTEXATTRIBARRAYPROC proc_enable_vertex_attrib_array; PFNGLENABLEVERTEXATTRIBARRAYPROC proc_enable_vertex_attrib_array;
PFNGLDRAWARRAYSEXTPROC proc_draw_arrays; PFNGLDRAWARRAYSEXTPROC proc_draw_arrays;
@ -423,6 +425,8 @@ int kmscon_context_new(struct kmscon_context **out, void *gbm)
(void*) eglGetProcAddress("glGetUniformLocation"); (void*) eglGetProcAddress("glGetUniformLocation");
ctx->proc_uniform_matrix_4fv = ctx->proc_uniform_matrix_4fv =
(void*) eglGetProcAddress("glUniformMatrix4fv"); (void*) eglGetProcAddress("glUniformMatrix4fv");
ctx->proc_uniform_1i =
(void*) eglGetProcAddress("glUniform1i");
ctx->proc_vertex_attrib_pointer = ctx->proc_vertex_attrib_pointer =
(void*) eglGetProcAddress("glVertexAttribPointer"); (void*) eglGetProcAddress("glVertexAttribPointer");
ctx->proc_enable_vertex_attrib_array = 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_program_info_log ||
!ctx->proc_get_uniform_location || !ctx->proc_get_uniform_location ||
!ctx->proc_uniform_matrix_4fv || !ctx->proc_uniform_matrix_4fv ||
!ctx->proc_uniform_1i ||
!ctx->proc_vertex_attrib_pointer || !ctx->proc_vertex_attrib_pointer ||
!ctx->proc_enable_vertex_attrib_array || !ctx->proc_enable_vertex_attrib_array ||
!ctx->proc_draw_arrays) { !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); 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, int renderbuffer_new(struct renderbuffer **out, struct kmscon_context *ctx,
void *bo) void *bo)
{ {

View File

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