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:
parent
096f0cadc7
commit
650c7077f1
@ -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 \
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
mkdir -p m4/
|
||||
autoreconf -i
|
||||
./configure --enable-debug --enable-gles2 $*
|
||||
./configure --enable-debug $*
|
||||
|
21
configure.ac
21
configure.ac
@ -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])
|
||||
|
@ -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"
|
||||
|
||||
|
1072
src/output.c
1072
src/output.c
File diff suppressed because it is too large
Load Diff
166
src/output.h
166
src/output.h
@ -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 */
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user