diff options
author | Alfred E. Heggestad <aeh@db.org> | 2014-02-09 11:50:07 +0100 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2014-02-09 11:50:07 +0100 |
commit | 98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch) | |
tree | ebc6ec71f44bff8c42e4eefced61948623df02fc /modules/opengles | |
parent | e6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff) |
baresip 0.4.10
Diffstat (limited to 'modules/opengles')
-rw-r--r-- | modules/opengles/context.m | 115 | ||||
-rw-r--r-- | modules/opengles/module.mk | 16 | ||||
-rw-r--r-- | modules/opengles/opengles.c | 295 | ||||
-rw-r--r-- | modules/opengles/opengles.h | 28 |
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); |