Remove old output subsystem

This subsystem is no longer used so remove it.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-03-23 14:29:25 +01:00
parent 096f0cadc7
commit 650c7077f1
8 changed files with 5 additions and 2404 deletions

View File

@ -40,9 +40,6 @@ nodist_libkmscon_core_la_SOURCES = \
libkmscon_core_la_SOURCES = \
src/misc.c src/misc.h \
src/console.c src/console.h \
src/output.c src/output.h \
src/output_context.c \
src/output_math.c \
src/console_cell.c \
src/unicode.c src/unicode.h \
src/log.c src/log.h \

View File

@ -1,4 +1,4 @@
#!/bin/sh
mkdir -p m4/
autoreconf -i
./configure --enable-debug --enable-gles2 $*
./configure --enable-debug $*

View File

@ -33,25 +33,12 @@ PKG_CHECK_MODULES([GBM], [gbm])
AC_SUBST(GBM_CFLAGS)
AC_SUBST(GBM_LIBS)
AC_MSG_CHECKING([whether to use OpenGLES2 instead of OpenGL])
AC_ARG_ENABLE([gles2],
[AS_HELP_STRING([--enable-gles2], [whether to use OpenGLES2 instead of OpenGL])],
[force_gles2="$enableval";
AC_DEFINE([USE_GLES2], [1], [Define if OpenGLES2 should be used])],
[force_gles2=no])
AC_MSG_RESULT([$force_gles2])
if test x$force_gles2 = xyes ; then
PKG_CHECK_MODULES([OPENGLES2], [glesv2])
OPENGL_CFLAGS=$OPENGLES2_CFLAGS
OPENGL_LIBS=$OPENGLES2_LIBS
else
PKG_CHECK_MODULES([OPENGL], [gl])
fi
PKG_CHECK_MODULES([OPENGL], [glesv2])
AC_SUBST(OPENGL_CFLAGS)
AC_SUBST(OPENGL_LIBS)
AC_DEFINE([UTERM_HAVE_DRM], [1], [Use DRM uterm backend])
PKG_CHECK_MODULES([UDEV], [libudev])
AC_SUBST(UDEV_CFLAGS)
AC_SUBST(UDEV_LIBS)
@ -120,7 +107,5 @@ else
AC_DEFINE([LOG_ENABLE_DEBUG], [1], [Enable debug for log subsystem])
fi
AC_DEFINE([UTERM_HAVE_DRM], [1], [Use DRM uterm backend])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT([src/genshader.c])

View File

@ -39,8 +39,8 @@
#include <stdlib.h>
#include <string.h>
#include "gl.h"
#include "output.h"
#include "log.h"
#include "uterm.h"
#define LOG_SUBSYSTEM "gl"

File diff suppressed because it is too large Load Diff

View File

@ -1,166 +0,0 @@
/*
* kmscon - KMS/DRM output handling
*
* Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
* Copyright (c) 2011 University of Tuebingen
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* KMS/DRM Output Handling
* This module provides a compositor object which manages the different outputs.
* Each output object belongs to a connected monitor.
* After creating a compositor object it will create a list of all available
* outputs. All outputs are disconnected by default. If you connect an
* output, a framebuffer with two renderbuffers is registered and you can start
* drawing to it using double-buffering.
* You can connect as many outputs as you want.
*
* To allow other applications to access the DRM you can put a compositor asleep
* and wake it up. When the compositor is asleep, the OpenGL context and
* framebuffers are still available, however, you cannot add or remove outputs
* unless the compositor is awake. You also cannot modify output modes or other
* output settings. It is recommended to avoid accessing the output objects at
* all as most of the functions simply return -EINVAL while being asleep.
*
* When waking up the compositor, it rereads all connected outputs. If a
* previously connected output has gone, it disconnects the output, removes
* the associated framebuffer and context and unbinds the output object from the
* compositor. If you own a reference to the output object, you should unref it
* now.
* You should also reread the output list for newly connected outputs.
* You can also force the compositor to reread all outputs if you noticed any
* monitor hotplugging (for instance via udev).
*
* An output may be used in different modes. Each output chooses one mode by
* default, however, you can always switch to another mode if you want another
* pixel-resolution, color-mode, etc. When switching modes, the current
* framebuffer is destroyed and a new one is created.
*/
#ifndef KMSCON_OUTPUT_H
#define KMSCON_OUTPUT_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
struct kmscon_mode;
struct kmscon_framebuffer;
struct kmscon_output;
struct kmscon_context;
struct kmscon_compositor;
/* output modes */
int kmscon_mode_new(struct kmscon_mode **out);
void kmscon_mode_ref(struct kmscon_mode *mode);
void kmscon_mode_unref(struct kmscon_mode *mode);
struct kmscon_mode *kmscon_mode_next(struct kmscon_mode *mode);
const char *kmscon_mode_get_name(const struct kmscon_mode *mode);
uint32_t kmscon_mode_get_width(const struct kmscon_mode *mode);
uint32_t kmscon_mode_get_height(const struct kmscon_mode *mode);
/* framebuffer */
int kmscon_framebuffer_new(struct kmscon_framebuffer **out,
struct kmscon_context *ctx, void *bo1, void *bo2);
void kmscon_framebuffer_destroy(struct kmscon_framebuffer *fb);
void kmscon_framebuffer_use(struct kmscon_framebuffer *fb);
int kmscon_framebuffer_swap(struct kmscon_framebuffer *fb);
/* compositor outputs */
int kmscon_output_new(struct kmscon_output **out);
void kmscon_output_ref(struct kmscon_output *output);
void kmscon_output_unref(struct kmscon_output *output);
bool kmscon_output_is_awake(struct kmscon_output *output);
struct kmscon_output *kmscon_output_next(struct kmscon_output *output);
struct kmscon_mode *kmscon_output_get_modes(struct kmscon_output *output);
struct kmscon_mode *kmscon_output_get_current(struct kmscon_output *output);
struct kmscon_mode *kmscon_output_get_default(struct kmscon_output *output);
int kmscon_output_activate(struct kmscon_output *output,
struct kmscon_mode *mode);
void kmscon_output_deactivate(struct kmscon_output *output);
bool kmscon_output_is_active(struct kmscon_output *output);
int kmscon_output_use(struct kmscon_output *output);
int kmscon_output_swap(struct kmscon_output *output);
/* math helpers */
struct kmscon_m4_stack;
void kmscon_m4_identity(float *m);
void kmscon_m4_copy(float *dest, const float *src);
void kmscon_m4_mult(float *n, const float *m);
void kmscon_m4_trans(float *m, float x, float y, float z);
void kmscon_m4_scale(float *m, float x, float y, float z);
void kmscon_m4_transp(float *m);
void kmscon_m4_transp_dest(float *dest, const float *src);
int kmscon_m4_stack_new(struct kmscon_m4_stack **out);
void kmscon_m4_stack_free(struct kmscon_m4_stack *stack);
float *kmscon_m4_stack_push(struct kmscon_m4_stack *stack);
float *kmscon_m4_stack_pop(struct kmscon_m4_stack *stack);
float *kmscon_m4_stack_tip(struct kmscon_m4_stack *stack);
/* drawing contexts */
int kmscon_context_new(struct kmscon_context **out, void *gbm);
void kmscon_context_destroy(struct kmscon_context *ctx);
int kmscon_context_use(struct kmscon_context *ctx);
bool kmscon_context_is_active(struct kmscon_context *ctx);
void kmscon_context_flush(struct kmscon_context *ctx);
void kmscon_context_viewport(struct kmscon_context *ctx,
unsigned int width, unsigned int height);
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, const float *m);
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 */
int kmscon_compositor_new(struct kmscon_compositor **out);
void kmscon_compositor_ref(struct kmscon_compositor *comp);
void kmscon_compositor_unref(struct kmscon_compositor *comp);
void kmscon_compositor_sleep(struct kmscon_compositor *comp);
int kmscon_compositor_wake_up(struct kmscon_compositor *comp);
bool kmscon_compositor_is_asleep(struct kmscon_compositor *comp);
int kmscon_compositor_use(struct kmscon_compositor *comp);
struct kmscon_context *kmscon_compositor_get_context(
struct kmscon_compositor *comp);
struct kmscon_output *kmscon_compositor_get_outputs(
struct kmscon_compositor *comp);
int kmscon_compositor_refresh(struct kmscon_compositor *comp);
#endif /* KMSCON_OUTPUT_H */

View File

@ -1,862 +0,0 @@
/*
* kmscon - Drawing Contexts
*
* Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
* Copyright (c) 2011 University of Tuebingen
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Drawing Contexts
* This provides a drwaing context for compositor objects and associated
* framebuffers for output objects. It is implemented with OpenGL as backend.
*/
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#ifdef USE_GLES2
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else
#include <GL/gl.h>
#include <GL/glext.h>
#endif
#include "log.h"
#include "output.h"
/* OpenGL extension definitions */
typedef void (*PFNGLGENRENDERBUFFERSPROC)
(GLsizei n, GLuint *renderbuffers);
typedef void (*PFNGLBINDRENDERBUFFERPROC)
(GLenum target, GLuint renderbuffer);
typedef void (*PFNGLDELETERENDERBUFFERSPROC)
(GLsizei n, const GLuint *renderbuffers);
typedef void (*PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target,
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef GLenum (*PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
typedef void (*PFNGLGENFRAMEBUFFERSPROC)
(GLsizei n, GLuint *framebuffers);
typedef void (*PFNGLBINDFRAMEBUFFERPROC)
(GLenum target, GLuint framebuffer);
typedef void (*PFNGLDELETEFRAMEBUFFERSPROC)
(GLsizei n, const GLuint *framebuffers);
typedef GLuint (*PFNGLCREATESHADERPROC) (GLenum type);
typedef void (*PFNGLDELETESHADERPROC) (GLuint shader);
typedef void (*PFNGLSHADERSOURCEPROC) (GLuint shader,
GLsizei count, const GLchar* *string, const GLint *length);
typedef void (*PFNGLCOMPILESHADERPROC) (GLuint shader);
typedef void (*PFNGLGETSHADERIVPROC)
(GLuint shader, GLenum pname, GLint *params);
typedef void (*PFNGLGETSHADERINFOLOGPROC)
(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef GLuint (*PFNGLCREATEPROGRAMPROC) (void);
typedef void (*PFNGLDELETEPROGRAMPROC) (GLuint program);
typedef void (*PFNGLUSEPROGRAMPROC) (GLuint program);
typedef void (*PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
typedef void (*PFNGLBINDATTRIBLOCATIONPROC)
(GLuint program, GLuint index, const GLchar *name);
typedef void (*PFNGLLINKPROGRAMPROC) (GLuint program);
typedef void (*PFNGLGETPROGRAMIVPROC)
(GLuint program, GLenum pname, GLint *params);
typedef void (*PFNGLGETPROGRAMINFOLOGPROC)
(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
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);
typedef void (*PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (*PFNGLDRAWARRAYSEXTPROC)
(GLenum mode, GLint first, GLsizei count);
struct kmscon_context {
EGLDisplay display;
EGLContext context;
GLuint def_program;
GLuint def_vshader;
GLuint def_fshader;
GLuint def_uni_projection;
GLuint tex_program;
GLuint tex_vshader;
GLuint tex_fshader;
GLuint tex_uni_projection;
GLuint tex_uni_texture;
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC proc_rbuf_storage;
PFNEGLCREATEIMAGEKHRPROC proc_create_image;
PFNEGLDESTROYIMAGEKHRPROC proc_destroy_image;
PFNGLGENRENDERBUFFERSPROC proc_gen_renderbuffers;
PFNGLBINDRENDERBUFFERPROC proc_bind_renderbuffer;
PFNGLDELETERENDERBUFFERSPROC proc_delete_renderbuffers;
PFNGLFRAMEBUFFERRENDERBUFFERPROC proc_framebuffer_renderbuffer;
PFNGLCHECKFRAMEBUFFERSTATUSPROC proc_check_framebuffer_status;
PFNGLGENFRAMEBUFFERSPROC proc_gen_framebuffers;
PFNGLBINDFRAMEBUFFERPROC proc_bind_framebuffer;
PFNGLDELETEFRAMEBUFFERSPROC proc_delete_framebuffers;
PFNGLCREATESHADERPROC proc_create_shader;
PFNGLDELETESHADERPROC proc_delete_shader;
PFNGLSHADERSOURCEPROC proc_shader_source;
PFNGLCOMPILESHADERPROC proc_compile_shader;
PFNGLGETSHADERIVPROC proc_get_shader_iv;
PFNGLGETSHADERINFOLOGPROC proc_get_shader_info_log;
PFNGLCREATEPROGRAMPROC proc_create_program;
PFNGLDELETEPROGRAMPROC proc_delete_program;
PFNGLUSEPROGRAMPROC proc_use_program;
PFNGLATTACHSHADERPROC proc_attach_shader;
PFNGLBINDATTRIBLOCATIONPROC proc_bind_attrib_location;
PFNGLLINKPROGRAMPROC proc_link_program;
PFNGLGETPROGRAMIVPROC proc_get_program_iv;
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;
};
struct renderbuffer {
struct kmscon_context *ctx;
EGLImageKHR image;
GLuint rb;
};
struct kmscon_framebuffer {
struct kmscon_context *ctx;
GLuint fb;
struct renderbuffer *rbs[2];
unsigned int current_rb;
};
/*
* Clear the GL error stack. The standard says that the error value is just a
* single value and no list/stack. However, multiple error fields may be defined
* and glGetError() returns only one of them until all are cleared. Hence, we
* loop until no more error is retrieved.
*/
static void clear_gl_error()
{
GLenum err;
do {
err = glGetError();
} while (err != GL_NO_ERROR);
}
/* return true if there is a pending GL error */
static bool has_gl_error()
{
GLenum err;
err = glGetError();
if (err != GL_NO_ERROR) {
log_err("context: GL error %d\n", err);
return true;
}
return false;
}
/* external shader sources; generated during build */
extern const char *kmscon_vert_def;
extern const char *kmscon_frag_def;
extern const char *kmscon_vert_tex;
extern const char *kmscon_frag_tex;
static int compile_shader(struct kmscon_context *ctx, GLenum type,
const char *source)
{
char msg[512];
GLint status = 1;
GLuint s;
s = ctx->proc_create_shader(type);
if (s == GL_NONE) {
log_warn("context: cannot allocate GL shader\n");
return GL_NONE;
}
ctx->proc_shader_source(s, 1, &source, NULL);
ctx->proc_compile_shader(s);
ctx->proc_get_shader_iv(s, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
msg[0] = 0;
ctx->proc_get_shader_info_log(s, sizeof(msg), NULL, msg);
log_warn("context: cannot compile shader: %s\n", msg);
return GL_NONE;
}
return s;
}
static int init_def_shader(struct kmscon_context *ctx)
{
char msg[512];
GLint status = 1;
int ret;
if (!ctx)
return -EINVAL;
ctx->def_vshader = compile_shader(ctx, GL_VERTEX_SHADER,
kmscon_vert_def);
if (ctx->def_vshader == GL_NONE)
return -EFAULT;
ctx->def_fshader = compile_shader(ctx, GL_FRAGMENT_SHADER,
kmscon_frag_def);
if (ctx->def_fshader == GL_NONE) {
ret = -EFAULT;
goto err_vshader;
}
ctx->def_program = ctx->proc_create_program();
ctx->proc_attach_shader(ctx->def_program, ctx->def_vshader);
ctx->proc_attach_shader(ctx->def_program, ctx->def_fshader);
ctx->proc_bind_attrib_location(ctx->def_program, 0, "position");
ctx->proc_bind_attrib_location(ctx->def_program, 1, "color");
ctx->proc_link_program(ctx->def_program);
ctx->proc_get_program_iv(ctx->def_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
msg[0] = 0;
ctx->proc_get_program_info_log(ctx->def_program, sizeof(msg),
NULL, msg);
log_warn("context: cannot link shader: %s\n", msg);
ret = -EFAULT;
goto err_link;
}
ctx->def_uni_projection =
ctx->proc_get_uniform_location(ctx->def_program, "projection");
return 0;
err_link:
ctx->proc_delete_program(ctx->def_program);
ctx->proc_delete_shader(ctx->def_fshader);
err_vshader:
ctx->proc_delete_shader(ctx->def_vshader);
return ret;
}
static int init_tex_shader(struct kmscon_context *ctx)
{
char msg[512];
GLint status = 1;
int ret;
if (!ctx)
return -EINVAL;
ctx->tex_vshader = compile_shader(ctx, GL_VERTEX_SHADER,
kmscon_vert_tex);
if (ctx->tex_vshader == GL_NONE)
return -EFAULT;
ctx->tex_fshader = compile_shader(ctx, GL_FRAGMENT_SHADER,
kmscon_frag_tex);
if (ctx->tex_fshader == GL_NONE) {
ret = -EFAULT;
goto err_vshader;
}
ctx->tex_program = ctx->proc_create_program();
ctx->proc_attach_shader(ctx->tex_program, ctx->tex_vshader);
ctx->proc_attach_shader(ctx->tex_program, ctx->tex_fshader);
ctx->proc_bind_attrib_location(ctx->tex_program, 0, "position");
ctx->proc_bind_attrib_location(ctx->tex_program, 1, "texture_position");
ctx->proc_link_program(ctx->tex_program);
ctx->proc_get_program_iv(ctx->tex_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
msg[0] = 0;
ctx->proc_get_program_info_log(ctx->tex_program, sizeof(msg),
NULL, msg);
log_warn("context: cannot link shader: %s\n", msg);
ret = -EFAULT;
goto err_link;
}
ctx->tex_uni_projection =
ctx->proc_get_uniform_location(ctx->tex_program, "projection");
ctx->tex_uni_texture =
ctx->proc_get_uniform_location(ctx->tex_program, "texture");
return 0;
err_link:
ctx->proc_delete_program(ctx->tex_program);
ctx->proc_delete_shader(ctx->tex_fshader);
err_vshader:
ctx->proc_delete_shader(ctx->tex_vshader);
return ret;
}
static int init_shader(struct kmscon_context *ctx)
{
int ret;
ret = init_def_shader(ctx);
if (ret)
return ret;
ret = init_tex_shader(ctx);
if (ret) {
ctx->proc_delete_program(ctx->def_program);
ctx->proc_delete_shader(ctx->def_fshader);
ctx->proc_delete_shader(ctx->def_vshader);
return ret;
}
return 0;
}
static void destroy_shader(struct kmscon_context *ctx)
{
if (!ctx)
return;
ctx->proc_delete_program(ctx->tex_program);
ctx->proc_delete_shader(ctx->tex_fshader);
ctx->proc_delete_shader(ctx->tex_vshader);
ctx->proc_delete_program(ctx->def_program);
ctx->proc_delete_shader(ctx->def_fshader);
ctx->proc_delete_shader(ctx->def_vshader);
}
/*
* Create the GL context
* This uses the EGL library for context creation and needs a valid gbm device
* as argument. The caller must provide a valid gbm device as \gbm. We do not
* touch \gbm at all but pass it to EGL. The \gbm object must live as long as we
* do.
*/
int kmscon_context_new(struct kmscon_context **out, void *gbm)
{
struct kmscon_context *ctx;
EGLint major, minor;
int ret;
const char *ext;
EGLenum api;
#ifdef USE_GLES2
static const EGLint ctx_attribs[] =
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
#else
static const EGLint *ctx_attribs = NULL;
#endif
if (!out || !gbm)
return -EINVAL;
log_debug("context: new GL context\n");
ctx = malloc(sizeof(*ctx));
if (!ctx)
return -ENOMEM;
memset(ctx, 0, sizeof(*ctx));
ctx->display = eglGetDisplay((EGLNativeDisplayType) gbm);
if (!ctx->display) {
log_warn("context: cannot get EGL display\n");
ret = -EFAULT;
goto err_free;
}
ret = eglInitialize(ctx->display, &major, &minor);
if (!ret) {
log_warn("context: cannot initialize EGL display\n");
ret = -EFAULT;
goto err_free;
}
ext = eglQueryString(ctx->display, EGL_EXTENSIONS);
if (!ext || !strstr(ext, "EGL_KHR_surfaceless_opengl")) {
log_warn("context: surfaceless EGL not supported\n");
ret = -ENOTSUP;
goto err_display;
}
#ifdef USE_GLES2
api = EGL_OPENGL_ES_API;
#else
api = EGL_OPENGL_API;
#endif
if (!eglBindAPI(api)) {
log_warn("context: cannot bind EGL OpenGL API\n");
ret = -EFAULT;
goto err_display;
}
ctx->context = eglCreateContext(ctx->display, NULL, EGL_NO_CONTEXT,
ctx_attribs);
if (!ctx->context) {
log_warn("context: cannot create EGL context\n");
ret = -EFAULT;
goto err_display;
}
if (!eglMakeCurrent(ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
ctx->context)) {
log_warn("context: cannot use EGL context\n");
ret = -EFAULT;
goto err_ctx;
}
ctx->proc_rbuf_storage = (void*)
eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
ctx->proc_create_image =
(void*) eglGetProcAddress("eglCreateImageKHR");
ctx->proc_destroy_image =
(void*) eglGetProcAddress("eglDestroyImageKHR");
ctx->proc_gen_renderbuffers =
(void*) eglGetProcAddress("glGenRenderbuffers");
ctx->proc_bind_renderbuffer =
(void*) eglGetProcAddress("glBindRenderbuffer");
ctx->proc_delete_renderbuffers =
(void*) eglGetProcAddress("glDeleteRenderbuffers");
ctx->proc_framebuffer_renderbuffer =
(void*) eglGetProcAddress("glFramebufferRenderbuffer");
ctx->proc_check_framebuffer_status =
(void*) eglGetProcAddress("glCheckFramebufferStatus");
ctx->proc_gen_framebuffers =
(void*) eglGetProcAddress("glGenFramebuffers");
ctx->proc_bind_framebuffer =
(void*) eglGetProcAddress("glBindFramebuffer");
ctx->proc_delete_framebuffers =
(void*) eglGetProcAddress("glDeleteFramebuffers");
ctx->proc_create_shader =
(void*) eglGetProcAddress("glCreateShader");
ctx->proc_delete_shader =
(void*) eglGetProcAddress("glDeleteShader");
ctx->proc_shader_source =
(void*) eglGetProcAddress("glShaderSource");
ctx->proc_compile_shader =
(void*) eglGetProcAddress("glCompileShader");
ctx->proc_get_shader_iv =
(void*) eglGetProcAddress("glGetShaderiv");
ctx->proc_get_shader_info_log =
(void*) eglGetProcAddress("glGetShaderInfoLog");
ctx->proc_create_program =
(void*) eglGetProcAddress("glCreateProgram");
ctx->proc_delete_program =
(void*) eglGetProcAddress("glDeleteProgram");
ctx->proc_use_program =
(void*) eglGetProcAddress("glUseProgram");
ctx->proc_attach_shader =
(void*) eglGetProcAddress("glAttachShader");
ctx->proc_bind_attrib_location =
(void*) eglGetProcAddress("glBindAttribLocation");
ctx->proc_link_program =
(void*) eglGetProcAddress("glLinkProgram");
ctx->proc_get_program_iv =
(void*) eglGetProcAddress("glGetProgramiv");
ctx->proc_get_program_info_log =
(void*) eglGetProcAddress("glGetProgramInfoLog");
ctx->proc_get_uniform_location =
(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 =
(void*) eglGetProcAddress("glEnableVertexAttribArray");
ctx->proc_draw_arrays =
(void*) eglGetProcAddress("glDrawArraysEXT");
if (!ctx->proc_rbuf_storage || !ctx->proc_create_image ||
!ctx->proc_destroy_image) {
log_warn("context: KHR images not supported\n");
ret = -ENOTSUP;
goto err_ctx;
} else if (!ctx->proc_gen_renderbuffers ||
!ctx->proc_bind_renderbuffer ||
!ctx->proc_delete_renderbuffers ||
!ctx->proc_framebuffer_renderbuffer ||
!ctx->proc_check_framebuffer_status) {
log_warn("context: renderbuffers not supported\n");
ret = -ENOTSUP;
goto err_ctx;
} else if (!ctx->proc_create_shader ||
!ctx->proc_delete_shader ||
!ctx->proc_shader_source ||
!ctx->proc_compile_shader ||
!ctx->proc_get_shader_iv ||
!ctx->proc_get_shader_info_log) {
log_warn("context: shaders not supported\n");
ret = -ENOTSUP;
goto err_ctx;
} else if (!ctx->proc_create_program ||
!ctx->proc_delete_program ||
!ctx->proc_use_program ||
!ctx->proc_attach_shader ||
!ctx->proc_bind_attrib_location ||
!ctx->proc_link_program ||
!ctx->proc_get_program_iv ||
!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) {
log_warn("context: shaders not supported\n");
ret = -ENOTSUP;
goto err_ctx;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ret = init_shader(ctx);
if (ret)
goto err_ctx;
*out = ctx;
return 0;
err_ctx:
eglDestroyContext(ctx->display, ctx->context);
err_display:
eglTerminate(ctx->display);
err_free:
free(ctx);
return ret;
}
void kmscon_context_destroy(struct kmscon_context *ctx)
{
if (!ctx)
return;
destroy_shader(ctx);
eglDestroyContext(ctx->display, ctx->context);
eglTerminate(ctx->display);
free(ctx);
log_debug("context: destroying GL context\n");
}
int kmscon_context_use(struct kmscon_context *ctx)
{
if (!ctx)
return -EINVAL;
if (!eglMakeCurrent(ctx->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
ctx->context)) {
log_warn("context: cannot use EGL context\n");
return -EFAULT;
}
return 0;
}
bool kmscon_context_is_active(struct kmscon_context *ctx)
{
if (!ctx)
return false;
return ctx->context == eglGetCurrentContext();
}
void kmscon_context_flush(struct kmscon_context *ctx)
{
if (!ctx)
return;
glFinish();
}
void kmscon_context_viewport(struct kmscon_context *ctx,
unsigned int width, unsigned int height)
{
if (!ctx)
return;
glViewport(0, 0, width, height);
}
void kmscon_context_clear(struct kmscon_context *ctx)
{
if (!ctx)
return;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
void kmscon_context_draw_def(struct kmscon_context *ctx, float *vertices,
float *colors, size_t num)
{
float m[16] = { 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
if (!ctx)
return;
ctx->proc_use_program(ctx->def_program);
ctx->proc_uniform_matrix_4fv(ctx->def_uni_projection, 1, GL_FALSE, m);
ctx->proc_vertex_attrib_pointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
ctx->proc_vertex_attrib_pointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
ctx->proc_enable_vertex_attrib_array(0);
ctx->proc_enable_vertex_attrib_array(1);
ctx->proc_draw_arrays(GL_TRIANGLES, 0, num);
}
void kmscon_context_draw_tex(struct kmscon_context *ctx, const float *vertices,
const float *texcoords, size_t num, unsigned int tex, const float *m)
{
float mat[16];
if (!ctx)
return;
kmscon_m4_transp_dest(mat, m);
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, mat);
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_TRIANGLES, 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);
#ifdef USE_GLES2
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0, GL_BGRA_EXT,
GL_UNSIGNED_BYTE, buf);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA,
GL_UNSIGNED_BYTE, buf);
#endif
}
int renderbuffer_new(struct renderbuffer **out, struct kmscon_context *ctx,
void *bo)
{
struct renderbuffer *rb;
int ret;
if (!out || !ctx || !bo)
return -EINVAL;
rb = malloc(sizeof(*rb));
if (!rb)
return -ENOMEM;
memset(rb, 0, sizeof(*rb));
rb->ctx = ctx;
clear_gl_error();
rb->image = ctx->proc_create_image(ctx->display, NULL,
EGL_NATIVE_PIXMAP_KHR, bo, NULL);
if (!rb->image) {
log_warn("context: cannot create EGL image\n");
ret = -EFAULT;
goto err_free;
}
ctx->proc_gen_renderbuffers(1, &rb->rb);
ctx->proc_bind_renderbuffer(GL_RENDERBUFFER, rb->rb);
ctx->proc_rbuf_storage(GL_RENDERBUFFER, rb->image);
if (has_gl_error()) {
log_warn("context: cannot create renderbuffers\n");
ret = -EFAULT;
goto err_gl;
}
*out = rb;
return 0;
err_gl:
ctx->proc_bind_renderbuffer(GL_RENDERBUFFER, 0);
ctx->proc_delete_renderbuffers(1, &rb->rb);
ctx->proc_destroy_image(ctx->display, rb->image);
err_free:
free(rb);
return ret;
}
void renderbuffer_destroy(struct renderbuffer *rb)
{
if (!rb)
return;
rb->ctx->proc_bind_renderbuffer(GL_RENDERBUFFER, 0);
rb->ctx->proc_delete_renderbuffers(1, &rb->rb);
rb->ctx->proc_destroy_image(rb->ctx->display, rb->image);
free(rb);
}
int kmscon_framebuffer_new(struct kmscon_framebuffer **out,
struct kmscon_context *ctx, void *bo1, void *bo2)
{
struct kmscon_framebuffer *fb;
int ret;
if (!out || !ctx || !bo1 || !bo2)
return -EINVAL;
fb = malloc(sizeof(*fb));
if (!fb)
return -ENOMEM;
memset(fb, 0, sizeof(*fb));
fb->ctx = ctx;
ret = renderbuffer_new(&fb->rbs[0], ctx, bo1);
if (ret)
goto err_free;
ret = renderbuffer_new(&fb->rbs[1], ctx, bo2);
if (ret)
goto err_rb;
ctx->proc_gen_framebuffers(1, &fb->fb);
ctx->proc_bind_framebuffer(GL_FRAMEBUFFER, fb->fb);
ctx->proc_framebuffer_renderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb->rbs[0]->rb);
if (ctx->proc_check_framebuffer_status(GL_FRAMEBUFFER) !=
GL_FRAMEBUFFER_COMPLETE) {
log_warn("context: invalid GL framebuffer state\n");
ret = -EFAULT;
goto err_fb;
}
*out = fb;
return 0;
err_fb:
ctx->proc_bind_framebuffer(GL_FRAMEBUFFER, 0);
ctx->proc_delete_framebuffers(1, &fb->fb);
renderbuffer_destroy(fb->rbs[1]);
err_rb:
renderbuffer_destroy(fb->rbs[0]);
err_free:
free(fb);
return ret;
}
void kmscon_framebuffer_destroy(struct kmscon_framebuffer *fb)
{
if (!fb)
return;
fb->ctx->proc_bind_framebuffer(GL_FRAMEBUFFER, 0);
fb->ctx->proc_delete_framebuffers(1, &fb->fb);
renderbuffer_destroy(fb->rbs[1]);
renderbuffer_destroy(fb->rbs[0]);
free(fb);
}
void kmscon_framebuffer_use(struct kmscon_framebuffer *fb)
{
if (!fb)
return;
fb->ctx->proc_bind_framebuffer(GL_FRAMEBUFFER, fb->fb);
}
int kmscon_framebuffer_swap(struct kmscon_framebuffer *fb)
{
if (!fb)
return -EINVAL;
fb->current_rb ^= 1;
fb->ctx->proc_bind_framebuffer(GL_FRAMEBUFFER, fb->fb);
fb->ctx->proc_framebuffer_renderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
fb->rbs[fb->current_rb]->rb);
if (fb->ctx->proc_check_framebuffer_status(GL_FRAMEBUFFER) !=
GL_FRAMEBUFFER_COMPLETE)
log_warn("context: invalid GL framebuffer state\n");
return fb->current_rb;
}

View File

@ -1,281 +0,0 @@
/*
* kmscon - Math Helper
*
* Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
* Copyright (c) 2011 University of Tuebingen
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Math Helper
* Basic linear algebra.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "output.h"
struct kmscon_m4_entry {
struct kmscon_m4_entry *next;
float matrix[16];
};
struct kmscon_m4_stack {
struct kmscon_m4_entry stack;
struct kmscon_m4_entry *cache;
};
void kmscon_m4_identity(float *m)
{
if (!m)
return;
m[0] = 1;
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = 1;
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = 1;
m[11] = 0;
m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1;
}
void kmscon_m4_copy(float *dest, const float *src)
{
if (!dest || !src)
return;
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest[4] = src[4];
dest[5] = src[5];
dest[6] = src[6];
dest[7] = src[7];
dest[8] = src[8];
dest[9] = src[9];
dest[10] = src[10];
dest[11] = src[11];
dest[12] = src[12];
dest[13] = src[13];
dest[14] = src[14];
dest[15] = src[15];
}
void kmscon_m4_mult(float *n, const float *m)
{
float tmp[16];
unsigned int row, col, j;
for (row = 0; row < 4; ++row) {
for (col = 0; col < 4; ++col) {
tmp[row * 4 + col] = 0;
for (j = 0; j < 4; ++j)
tmp[row * 4 + col] +=
n[row * 4 + j] * m[j * 4 + col];
}
}
kmscon_m4_copy(n, tmp);
}
void kmscon_m4_trans(float *m, float x, float y, float z)
{
float trans[16] = { 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 };
kmscon_m4_mult(m, trans);
}
void kmscon_m4_scale(float *m, float x, float y, float z)
{
float scale[16] = { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 };
kmscon_m4_mult(m, scale);
}
void kmscon_m4_transp(float *m)
{
float tmp;
if (!m)
return;
tmp = m[1];
m[1] = m[4];
m[4] = tmp;
tmp = m[8];
m[8] = m[2];
m[2] = tmp;
tmp = m[3];
m[3] = m[12];
m[12] = tmp;
tmp = m[7];
m[7] = m[13];
m[13] = tmp;
tmp = m[11];
m[11] = m[14];
m[14] = tmp;
tmp = m[6];
m[6] = m[9];
m[9] = tmp;
}
void kmscon_m4_transp_dest(float *dest, const float *src)
{
if (!dest || !src)
return;
dest[0] = src[0];
dest[5] = src[5];
dest[10] = src[10];
dest[15] = src[15];
dest[1] = src[4];
dest[4] = src[1];
dest[8] = src[2];
dest[2] = src[8];
dest[3] = src[12];
dest[12] = src[3];
dest[7] = src[13];
dest[13] = src[7];
dest[11] = src[14];
dest[14] = src[11];
dest[6] = src[9];
dest[9] = src[6];
}
int kmscon_m4_stack_new(struct kmscon_m4_stack **out)
{
struct kmscon_m4_stack *stack;
if (!out)
return -EINVAL;
stack = malloc(sizeof(*stack));
if (!stack)
return -ENOMEM;
memset(stack, 0, sizeof(*stack));
kmscon_m4_identity(stack->stack.matrix);
*out = stack;
return 0;
}
void kmscon_m4_stack_free(struct kmscon_m4_stack *stack)
{
struct kmscon_m4_entry *tmp;
if (!stack)
return;
while (stack->stack.next) {
tmp = stack->stack.next;
stack->stack.next = tmp->next;
free(tmp);
}
while (stack->cache) {
tmp = stack->cache;
stack->cache = tmp->next;
free(tmp);
}
free(stack);
}
float *kmscon_m4_stack_push(struct kmscon_m4_stack *stack)
{
struct kmscon_m4_entry *entry;
if (stack->cache) {
entry = stack->cache;
stack->cache = entry->next;
} else {
entry = malloc(sizeof(*entry));
if (!entry)
return NULL;
}
kmscon_m4_copy(entry->matrix, stack->stack.matrix);
entry->next = stack->stack.next;
stack->stack.next = entry;
return stack->stack.matrix;
}
float *kmscon_m4_stack_pop(struct kmscon_m4_stack *stack)
{
struct kmscon_m4_entry *entry;
if (!stack)
return NULL;
entry = stack->stack.next;
if (!entry) {
kmscon_m4_identity(stack->stack.matrix);
return stack->stack.matrix;
}
stack->stack.next = entry->next;
entry->next = stack->cache;
stack->cache = entry;
kmscon_m4_copy(stack->stack.matrix, entry->matrix);
return stack->stack.matrix;
}
float *kmscon_m4_stack_tip(struct kmscon_m4_stack *stack)
{
if (!stack)
return NULL;
return stack->stack.matrix;
}