summaryrefslogtreecommitdiff
path: root/modules/opengles
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
committerAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
commit98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch)
treeebc6ec71f44bff8c42e4eefced61948623df02fc /modules/opengles
parente6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff)
baresip 0.4.10
Diffstat (limited to 'modules/opengles')
-rw-r--r--modules/opengles/context.m115
-rw-r--r--modules/opengles/module.mk16
-rw-r--r--modules/opengles/opengles.c295
-rw-r--r--modules/opengles/opengles.h28
4 files changed, 454 insertions, 0 deletions
diff --git a/modules/opengles/context.m b/modules/opengles/context.m
new file mode 100644
index 0000000..354c74f
--- /dev/null
+++ b/modules/opengles/context.m
@@ -0,0 +1,115 @@
+/**
+ * @file context.m OpenGLES Context for iOS
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include <UIKit/UIKit.h>
+#include <QuartzCore/CAEAGLLayer.h>
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+#include "opengles.h"
+
+
+@interface GlView : UIView
+{
+ struct vidisp_st *st;
+}
+@end
+
+
+static EAGLContext *ctx = NULL;
+
+
+@implementation GlView
+
+
++ (Class)layerClass
+{
+ return [CAEAGLLayer class];
+}
+
+
+- (id)initWithFrame:(CGRect)frame vidisp:(struct vidisp_st *)vst
+{
+ self = [super initWithFrame:frame];
+ if (!self)
+ return nil;
+
+ self.layer.opaque = YES;
+
+ st = vst;
+
+ return self;
+}
+
+
+- (void) render_sel:(id)unused
+{
+ (void)unused;
+
+ if (!ctx) {
+ UIWindow* window = [UIApplication sharedApplication].keyWindow;
+
+ ctx = [EAGLContext alloc];
+ [ctx initWithAPI:kEAGLRenderingAPIOpenGLES1];
+
+ [EAGLContext setCurrentContext:ctx];
+
+ [window addSubview:self];
+ [window bringSubviewToFront:self];
+
+ [window makeKeyAndVisible];
+ }
+
+ if (!st->framebuffer) {
+
+ opengles_addbuffers(st);
+
+ [ctx renderbufferStorage:GL_RENDERBUFFER_OES
+ fromDrawable:(CAEAGLLayer*)self.layer];
+ }
+
+ opengles_render(st);
+
+ [ctx presentRenderbuffer:GL_RENDERBUFFER_OES];
+}
+
+
+- (void) dealloc
+{
+ [ctx release];
+
+ [super dealloc];
+}
+
+
+@end
+
+
+void context_destroy(struct vidisp_st *st)
+{
+ [(UIView *)st->view release];
+}
+
+
+int context_init(struct vidisp_st *st)
+{
+ UIWindow* window = [UIApplication sharedApplication].keyWindow;
+
+ st->view = [[GlView new] initWithFrame:window.bounds vidisp:st];
+
+ return 0;
+}
+
+
+void context_render(struct vidisp_st *st)
+{
+ UIView *view = st->view;
+
+ [view performSelectorOnMainThread:@selector(render_sel:)
+ withObject:nil
+ waitUntilDone:YES];
+}
diff --git a/modules/opengles/module.mk b/modules/opengles/module.mk
new file mode 100644
index 0000000..a9c5300
--- /dev/null
+++ b/modules/opengles/module.mk
@@ -0,0 +1,16 @@
+#
+# module.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+MOD := opengles
+$(MOD)_SRCS += opengles.c
+
+ifeq ($(OS),darwin)
+$(MOD)_SRCS += context.m
+
+$(MOD)_LFLAGS += -lobjc -framework CoreGraphics -framework CoreFoundation
+endif
+
+include mk/mod.mk
diff --git a/modules/opengles/opengles.c b/modules/opengles/opengles.c
new file mode 100644
index 0000000..fa87012
--- /dev/null
+++ b/modules/opengles/opengles.c
@@ -0,0 +1,295 @@
+/**
+ * @file opengles.c Video driver for OpenGLES
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+#include "opengles.h"
+
+
+#define DEBUG_MODULE "opengles"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+
+
+static struct vidisp *vid;
+
+
+static int texture_init(struct vidisp_st *st)
+{
+ glGenTextures(1, &st->texture_id);
+ if (!st->texture_id)
+ return ENOMEM;
+
+ glBindTexture(GL_TEXTURE_2D, st->texture_id);
+ glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+ st->vf->size.w, st->vf->size.h, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, st->vf->data[0]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(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);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return 0;
+}
+
+
+static void texture_render(struct vidisp_st *st)
+{
+ static const GLfloat coords[4 * 2] = {
+ 0.0, 1.0,
+ 1.0, 1.0,
+ 0.0, 0.0,
+ 1.0, 0.0
+ };
+
+ glBindTexture(GL_TEXTURE_2D, st->texture_id);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+ st->vf->size.w, st->vf->size.h, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, st->vf->data[0]);
+
+ /* Setup the vertices */
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, st->vertices);
+
+ /* Setup the texture coordinates */
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, coords);
+
+ glBindTexture(GL_TEXTURE_2D, st->texture_id);
+
+ glEnable(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(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);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisable(GL_TEXTURE_2D);
+}
+
+
+static void setup_layout(struct vidisp_st *st, const struct vidsz *screensz,
+ struct vidrect *ortho, struct vidrect *vp)
+{
+ int x, y, w, h, i = 0;
+
+ w = st->vf->size.w;
+ h = st->vf->size.h;
+
+ st->vertices[i++] = 0;
+ st->vertices[i++] = 0;
+ st->vertices[i++] = 0;
+ st->vertices[i++] = w;
+ st->vertices[i++] = 0;
+ st->vertices[i++] = 0;
+ st->vertices[i++] = 0;
+ st->vertices[i++] = h;
+ st->vertices[i++] = 0;
+ st->vertices[i++] = w;
+ st->vertices[i++] = h;
+ st->vertices[i++] = 0;
+
+ x = (screensz->w - w) / 2;
+ y = (screensz->h - h) / 2;
+
+ if (x < 0) {
+ vp->x = 0;
+ ortho->x = -x;
+ }
+ else {
+ vp->x = x;
+ ortho->x = 0;
+ }
+
+ if (y < 0) {
+ vp->y = 0;
+ ortho->y = -y;
+ }
+ else {
+ vp->y = y;
+ ortho->y = 0;
+ }
+
+ vp->w = screensz->w - 2 * vp->x;
+ vp->h = screensz->h - 2 * vp->y;
+
+ ortho->w = w - ortho->x;
+ ortho->h = h - ortho->y;
+}
+
+
+void opengles_addbuffers(struct vidisp_st *st)
+{
+ glGenFramebuffersOES(1, &st->framebuffer);
+ glGenRenderbuffersOES(1, &st->renderbuffer);
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, st->framebuffer);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, st->renderbuffer);
+}
+
+
+void opengles_render(struct vidisp_st *st)
+{
+ if (!st->texture_id) {
+
+ struct vidrect ortho, vp;
+ struct vidsz bufsz;
+ int err = 0;
+
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
+ GL_RENDERBUFFER_WIDTH_OES,
+ (GLint *)&bufsz.w);
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,
+ GL_RENDERBUFFER_HEIGHT_OES,
+ (GLint *)&bufsz.h);
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, st->framebuffer);
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
+ GL_COLOR_ATTACHMENT0_OES,
+ GL_RENDERBUFFER_OES,
+ st->renderbuffer);
+
+ err = texture_init(st);
+ if (err)
+ return;
+
+ glBindRenderbufferOES(GL_FRAMEBUFFER_OES, st->renderbuffer);
+
+ setup_layout(st, &bufsz, &ortho, &vp);
+
+
+ /* Set up Viewports etc. */
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, st->framebuffer);
+
+ glViewport(vp.x, vp.y, vp.w, vp.h);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glOrthof(ortho.x, ortho.w, ortho.y, ortho.h, 0.0f, 1.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glDisable(GL_DEPTH_TEST);
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+
+ texture_render(st);
+
+ glDisable(GL_TEXTURE_2D);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glEnable(GL_DEPTH_TEST);
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, st->renderbuffer);
+}
+
+
+static void destructor(void *arg)
+{
+ struct vidisp_st *st = arg;
+
+ glDeleteTextures(1, &st->texture_id);
+ glDeleteFramebuffersOES(1, &st->framebuffer);
+ glDeleteRenderbuffersOES(1, &st->renderbuffer);
+
+ context_destroy(st);
+
+ mem_deref(st->vf);
+ mem_deref(st->vd);
+}
+
+
+static int opengles_alloc(struct vidisp_st **stp, struct vidisp *vd,
+ struct vidisp_prm *prm, const char *dev,
+ vidisp_resize_h *resizeh,
+ void *arg)
+{
+ struct vidisp_st *st;
+ int err = 0;
+
+ (void)prm;
+ (void)dev;
+ (void)resizeh;
+ (void)arg;
+
+ st = mem_zalloc(sizeof(*st), destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->vd = mem_ref(vd);
+
+ err = context_init(st);
+ if (err)
+ goto out;
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}
+
+
+static int opengles_display(struct vidisp_st *st, const char *title,
+ const struct vidframe *frame)
+{
+ int err;
+
+ (void)title;
+
+ if (!st->vf) {
+ if (frame->size.w & 3) {
+ DEBUG_WARNING("width must be multiple of 4\n");
+ return EINVAL;
+ }
+
+ err = vidframe_alloc(&st->vf, VID_FMT_RGB565, &frame->size);
+ if (err)
+ return err;
+ }
+
+ vidconv(st->vf, frame, NULL);
+
+ context_render(st);
+
+ return 0;
+}
+
+
+static int module_init(void)
+{
+ return vidisp_register(&vid, "opengles", opengles_alloc, NULL,
+ opengles_display, NULL);
+}
+
+
+static int module_close(void)
+{
+ vid = mem_deref(vid);
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(opengles) = {
+ "opengles",
+ "vidisp",
+ module_init,
+ module_close,
+};
diff --git a/modules/opengles/opengles.h b/modules/opengles/opengles.h
new file mode 100644
index 0000000..9eac3fb
--- /dev/null
+++ b/modules/opengles/opengles.h
@@ -0,0 +1,28 @@
+/**
+ * @file opengles.h Internal API to OpenGLES module
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+
+struct vidisp_st {
+ struct vidisp *vd;
+ struct vidframe *vf;
+
+ /* GLES: */
+ GLuint framebuffer;
+ GLuint renderbuffer;
+ GLuint texture_id;
+ GLfloat vertices[4 * 3];
+
+ void *view;
+};
+
+
+void opengles_addbuffers(struct vidisp_st *st);
+void opengles_render(struct vidisp_st *st);
+
+
+int context_init(struct vidisp_st *st);
+void context_destroy(struct vidisp_st *st);
+void context_render(struct vidisp_st *st);