#import <UIKit/UIKit.h>
#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+#include <QuartzCore/QuartzCore.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout_display.h>
-#include <vlc_vout_opengl.h>
+#include <vlc_opengl.h>
#define USE_OPENGL_ES 1
+
#include "opengl.h"
-#include <QuartzCore/QuartzCore.h>
/**
* Forward declarations
static void Close(vlc_object_t *);
static picture_pool_t *Pool(vout_display_t *vd, unsigned requested_count);
-static void PictureRender(vout_display_t *vd, picture_t *pic);
-static void PictureDisplay(vout_display_t *vd, picture_t *pic);
+static void PictureRender(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture);
+static void PictureDisplay(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture);
static int Control (vout_display_t *vd, int query, va_list ap);
-static int OpenglClean(vout_opengl_t *gl);
-static void OpenglSwap(vout_opengl_t *gl);
+static int OpenglClean(vlc_gl_t *gl);
+static void OpenglSwap(vlc_gl_t *gl);
/**
* Module declaration
@interface VLCOpenGLESVideoView : UIView
{
vout_display_t * _vd;
- EAGLContext * _context;
+ EAGLContext * _context;
GLuint _defaultFramebuffer;
- GLuint _colorRenderbuffer;
- BOOL _framebufferDirty;
+ GLuint _colorRenderbuffer;
+ BOOL _framebufferDirty;
}
- (id)initWithFrame:(CGRect)frame andVOutDisplay:(vout_display_t *)vd;
@property (readonly) EAGLContext * context;
VLCOpenGLESVideoView *glView;
UIView * container;
- vout_opengl_t gl;
- vout_display_opengl_t vgl;
+ vlc_gl_t gl;
+ vout_display_opengl_t *vgl;
picture_pool_t *pool;
picture_t *current;
/* Get our main view*/
nsPool = [[NSAutoreleasePool alloc] init];
- msg_Dbg(vd, "Creating VLCOpenGLESVideoView");
- sys->glView = [[VLCOpenGLESVideoView alloc] initWithFrame:[container bounds] andVOutDisplay:vd];
+ msg_Dbg(vd, "Creating VLCOpenGLESVideoView");
+ sys->glView = [[VLCOpenGLESVideoView alloc] initWithFrame:[container bounds] andVOutDisplay:vd];
if (!sys->glView)
goto error;
/* We don't wait, that means that we'll have to be careful about releasing
* container.
* That's why we'll release on main thread in Close(). */
- [container performSelectorOnMainThread:@selector(addSubview:) withObject:sys->glView waitUntilDone:NO];
+ [container performSelectorOnMainThread:@selector(addSubview:) withObject:sys->glView waitUntilDone:NO];
[nsPool drain];
nsPool = nil;
sys->gl.lock = OpenglClean; // We don't do locking, but sometimes we need to cleanup the framebuffer
sys->gl.unlock = NULL;
sys->gl.swap = OpenglSwap;
+ sys->gl.getProcAddress = NULL;
sys->gl.sys = sys;
- if (vout_display_opengl_Init(&sys->vgl, &vd->fmt, &sys->gl))
+ sys->vgl = vout_display_opengl_New(&vd->fmt, NULL, &sys->gl);
+ if (!sys->vgl)
{
sys->gl.sys = NULL;
goto error;
[sys->glView release];
if (sys->gl.sys != NULL)
- vout_display_opengl_Clean(&sys->vgl);
+ vout_display_opengl_Delete(sys->vgl);
free (sys);
}
static picture_pool_t *Pool(vout_display_t *vd, unsigned requested_count)
{
vout_display_sys_t *sys = vd->sys;
- VLC_UNUSED(requested_count);
if (!sys->pool)
- sys->pool = vout_display_opengl_GetPool (&sys->vgl);
+ sys->pool = vout_display_opengl_GetPool (sys->vgl, requested_count);
assert(sys->pool);
return sys->pool;
}
-static void PictureRender(vout_display_t *vd, picture_t *pic)
+static void PictureRender(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
{
vout_display_sys_t *sys = vd->sys;
- vout_display_opengl_Prepare( &sys->vgl, pic );
+ vout_display_opengl_Prepare( sys->vgl, pic, subpicture );
}
-static void PictureDisplay(vout_display_t *vd, picture_t *pic)
+static void PictureDisplay(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
{
vout_display_sys_t *sys = vd->sys;
- vout_display_opengl_Display(&sys->vgl, &vd->fmt );
+ vout_display_opengl_Display(sys->vgl, &vd->fmt );
picture_Release (pic);
sys->has_first_frame = true;
+ (void)subpicture;
}
static int Control (vout_display_t *vd, int query, va_list ap)
case VOUT_DISPLAY_GET_OPENGL:
{
- vout_opengl_t **gl = va_arg (ap, vout_opengl_t **);
+ vlc_gl_t **gl = va_arg (ap, vlc_gl_t **);
*gl = &sys->gl;
return VLC_SUCCESS;
}
* vout opengl callbacks
*****************************************************************************/
-static int OpenglClean(vout_opengl_t *gl) {
+static int OpenglClean(vlc_gl_t *gl) {
vout_display_sys_t *sys = gl->sys;
- [sys->glView cleanFramebuffer];
- return 0;
+ [sys->glView cleanFramebuffer];
+ return 0;
}
-static void OpenglSwap(vout_opengl_t *gl)
+static void OpenglSwap(vlc_gl_t *gl)
{
vout_display_sys_t *sys = gl->sys;
EAGLContext *context = [sys->glView context];
- [context presentRenderbuffer:GL_RENDERBUFFER_OES];
+ [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
/*****************************************************************************
*/
- (id)initWithFrame:(CGRect)frame andVOutDisplay:(vout_display_t *)vd {
- if (self = [super initWithFrame:frame]) {
- _vd = vd;
- CAEAGLLayer * eaglLayer = (CAEAGLLayer *)self.layer;
+ if (self = [super initWithFrame:frame]) {
+ _vd = vd;
+ CAEAGLLayer * eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
-// [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
- kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat,
- nil];
+// [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat,
+ nil];
- _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
- NSAssert(_context && [EAGLContext setCurrentContext:_context], @"Creating context");
+ _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+ NSAssert(_context && [EAGLContext setCurrentContext:_context], @"Creating context");
// This shouldn't need to be done on the main thread.
// Indeed, it works just fine from the render thread on iOS 3.2 to 4.1
// However, if you don't call it from the main thread, it doesn't work on iOS 4.2 beta 1
[self performSelectorOnMainThread:@selector(_createFramebuffer) withObject:nil waitUntilDone:YES];
- _framebufferDirty = NO;
+ _framebufferDirty = NO;
- [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
- }
+ [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
+ }
return self;
}
* Method called by UIKit when we have been resized
*/
- (void)layoutSubviews {
- // CAUTION : This is called from the main thread
- _framebufferDirty = YES;
+ // CAUTION : This is called from the main thread
+ _framebufferDirty = YES;
}
- (void)cleanFramebuffer {
- if (_framebufferDirty) {
- [self _destroyFramebuffer];
- [self _createFramebuffer];
- _framebufferDirty = NO;
- }
+ if (_framebufferDirty) {
+ [self _destroyFramebuffer];
+ [self _createFramebuffer];
+ _framebufferDirty = NO;
+ }
}
@end
@implementation VLCOpenGLESVideoView (Private)
- (void)_createFramebuffer {
- msg_Dbg(_vd, "Creating framebuffer for layer %p with bounds (%.1f,%.1f,%.1f,%.1f)", self.layer, self.layer.bounds.origin.x, self.layer.bounds.origin.y, self.layer.bounds.size.width, self.layer.bounds.size.height);
- [EAGLContext setCurrentContext:_context];
- // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
- glGenFramebuffersOES(1, &_defaultFramebuffer); // Generate one framebuffer, store it in _defaultFrameBuffer
- glGenRenderbuffersOES(1, &_colorRenderbuffer);
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, _defaultFramebuffer);
- glBindRenderbufferOES(GL_RENDERBUFFER_OES, _colorRenderbuffer);
-
- // This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
- // allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
- [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
- glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _colorRenderbuffer);
-
- GLuint backingWidth, backingHeight;
- glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
- glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
-
- if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
- msg_Err(_vd, "Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
- }
- [self _updateViewportWithBackingWitdh:backingWidth andBackingHeight:backingHeight];
+ msg_Dbg(_vd, "Creating framebuffer for layer %p with bounds (%.1f,%.1f,%.1f,%.1f)", self.layer, self.layer.bounds.origin.x, self.layer.bounds.origin.y, self.layer.bounds.size.width, self.layer.bounds.size.height);
+ [EAGLContext setCurrentContext:_context];
+ // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
+ glGenFramebuffersOES(1, &_defaultFramebuffer); // Generate one framebuffer, store it in _defaultFrameBuffer
+ glGenRenderbuffersOES(1, &_colorRenderbuffer);
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, _defaultFramebuffer);
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _colorRenderbuffer);
+
+ // This call associates the storage for the current render buffer with the EAGLDrawable (our CAEAGLLayer)
+ // allowing us to draw into a buffer that will later be rendered to screen wherever the layer is (which corresponds with our view).
+ [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _colorRenderbuffer);
+
+ GLuint backingWidth, backingHeight;
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
+
+ if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
+ msg_Err(_vd, "Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+ }
+ [self _updateViewportWithBackingWitdh:backingWidth andBackingHeight:backingHeight];
}
- (void)_updateViewportWithBackingWitdh:(GLuint)backingWidth andBackingHeight:(GLuint)backingHeight {
- msg_Dbg(_vd, "Reshaping to %dx%d", backingWidth, backingHeight);
+ msg_Dbg(_vd, "Reshaping to %dx%d", backingWidth, backingHeight);
- CGFloat width = (CGFloat)backingWidth;
- CGFloat height = (CGFloat)backingHeight;
+ CGFloat width = (CGFloat)backingWidth;
+ CGFloat height = (CGFloat)backingHeight;
GLint x = width, y = height;
- if (_vd) {
- CGFloat videoHeight = _vd->source.i_visible_height;
- CGFloat videoWidth = _vd->source.i_visible_width;
-
- GLint sarNum = _vd->source.i_sar_num;
- GLint sarDen = _vd->source.i_sar_den;
-
- if (height * videoWidth * sarNum < width * videoHeight * sarDen)
- {
- x = (height * videoWidth * sarNum) / (videoHeight * sarDen);
- y = height;
- }
- else
- {
- x = width;
- y = (width * videoHeight * sarDen) / (videoWidth * sarNum);
- }
- }
-
- [EAGLContext setCurrentContext:_context];
- glViewport((width - x) / 2, (height - y) / 2, x, y);
+ if (_vd) {
+ CGFloat videoHeight = _vd->source.i_visible_height;
+ CGFloat videoWidth = _vd->source.i_visible_width;
+
+ GLint sarNum = _vd->source.i_sar_num;
+ GLint sarDen = _vd->source.i_sar_den;
+
+ if (height * videoWidth * sarNum < width * videoHeight * sarDen)
+ {
+ x = (height * videoWidth * sarNum) / (videoHeight * sarDen);
+ y = height;
+ }
+ else
+ {
+ x = width;
+ y = (width * videoHeight * sarDen) / (videoWidth * sarNum);
+ }
+ }
+
+ [EAGLContext setCurrentContext:_context];
+ glViewport((width - x) / 2, (height - y) / 2, x, y);
}
- (void)_destroyFramebuffer {
- [EAGLContext setCurrentContext:_context];
- glDeleteFramebuffersOES(1, &_defaultFramebuffer);
- _defaultFramebuffer = 0;
- glDeleteRenderbuffersOES(1, &_colorRenderbuffer);
- _colorRenderbuffer = 0;
+ [EAGLContext setCurrentContext:_context];
+ glDeleteFramebuffersOES(1, &_defaultFramebuffer);
+ _defaultFramebuffer = 0;
+ glDeleteRenderbuffersOES(1, &_colorRenderbuffer);
+ _colorRenderbuffer = 0;
}
@end