xineopenglview.m

来自「linux下的MPEG1」· M 代码 · 共 771 行 · 第 1/2 页

M
771
字号
/* * Copyright (C) 2004 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA * *//*#define LOG*/#import <Cocoa/Cocoa.h>#import <OpenGL/OpenGL.h>#import <OpenGL/gl.h>#import <OpenGL/glext.h>#import "XineOpenGLView.h"#ifdef XINE_COMPILE#  include "xineutils.h"#else#  include <xine/xineutils.h>#endifNSString *XineViewDidResizeNotification EXPORTED = @"XineViewDidResizeNotification";static uint32_tNSColorToYUV(NSColor *color){    float           red, green, blue, alpha;    uint32_t        yuv;    unsigned char   r, g, b;    unsigned char   y, u, v;    NSColor *calibratedColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];    [calibratedColor getRed:&red green:&green blue:&blue alpha:&alpha];    r = red * 255;    g = green * 255;    b = blue * 255;    init_yuv_conversion();    y = COMPUTE_Y(r, g, b);    u = COMPUTE_U(r, g, b);    v = COMPUTE_V(r, g, b);    yuv = (y << 24) | (u << 16) | (y << 8) | v;    return yuv;}@implementation XineOpenGLView+ (NSOpenGLPixelFormat *)defaultPixelFormat{    NSOpenGLPixelFormatAttribute attributes[] = {        NSOpenGLPFAAccelerated,        NSOpenGLPFANoRecovery,        NSOpenGLPFADoubleBuffer,        NSOpenGLPFAColorSize,    24,        NSOpenGLPFAAlphaSize,    8,        NSOpenGLPFADepthSize,    24,        NSOpenGLPFAWindow,        0    };    return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease];}+ (NSOpenGLPixelFormat *)fullScreenPixelFormat{    NSOpenGLPixelFormatAttribute attributes[] = {        NSOpenGLPFAAccelerated,        NSOpenGLPFANoRecovery,        NSOpenGLPFADoubleBuffer,        NSOpenGLPFAColorSize,    24,        NSOpenGLPFAAlphaSize,    8,        NSOpenGLPFADepthSize,    24,        NSOpenGLPFAFullScreen,        NSOpenGLPFAScreenMask,   CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),        0    };        return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease];}- (id)initWithCoder:(NSCoder *)coder{    NSColor *color;    if ((self = [super initWithCoder:coder]) != nil) {        videoSize     = [self frame].size;        mutex         = [[NSRecursiveLock alloc] init];        currentCursor = [[NSCursor arrowCursor] retain];        if ([coder allowsKeyedCoding]) {            keepsVideoAspectRatio       = [coder decodeBoolForKey:@"keepsVideoAspectRatio"];            resizeViewOnVideoSizeChange = [coder decodeBoolForKey:@"resizeViewOnVideoSizeChange"];            color                       = [coder decodeObjectForKey:@"initialColor"];        }        else {  /* Must decode values in the same order as encodeWithCoder: */            [coder decodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio];            [coder decodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange];            color = [coder decodeObject];        }        [self setInitialColor:color];#ifdef LOG        NSLog(@"XineOpenGLView: initWithCoder called");#endif    }    return self;}- (id)initWithFrame:(NSRect)frame{    return [self initWithFrame:frame pixelFormat:[[self class] defaultPixelFormat]];}- (id)initWithFrame:(NSRect)frame pixelFormat:(NSOpenGLPixelFormat *)format{    format = (format ? : [[self class] defaultPixelFormat]);    if ((self = [super initWithFrame:frame pixelFormat:format]) != nil) {        videoSize     = frame.size;        mutex         = [[NSRecursiveLock alloc] init];        currentCursor = [[NSCursor arrowCursor] retain];        [self setInitialColor:nil];#ifdef LOG        NSLog(@"XineOpenGLView: initWithFrame called");#endif    }    return self;}- (void)dealloc{    if (isFullScreen) {        [self exitFullScreen];    }    if (texture) {        [[self openGLContext] makeCurrentContext];        glDeleteTextures(1, &texture);        texture = 0;    }    free(textureBuffer);    [currentCursor release], currentCursor = nil;    [initialColor  release], initialColor  = nil;    [delegate      release], delegate      = nil;    [controller    release], controller    = nil;    [mutex         release], mutex         = nil;    [super dealloc];}- (void)encodeWithCoder:(NSCoder *)coder{    [super encodeWithCoder:coder];        if ([coder allowsKeyedCoding]) {        [coder encodeBool:keepsVideoAspectRatio forKey:@"keepsVideoAspectRatio"];        [coder encodeBool:resizeViewOnVideoSizeChange forKey:@"resizeViewOnVideoSizeChange"];        [coder encodeObject:initialColor forKey:@"initialColor"];    }    else {        [coder encodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio];        [coder encodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange];        [coder encodeObject:initialColor];    }}- (NSOpenGLContext *)openGLContext{    NSOpenGLContext *context;    [mutex lock];    if (!(context = [[fullScreenContext retain] autorelease])) {        context = [[[super openGLContext] retain] autorelease];    }    else if (!isFullScreenPrepared) {        [self prepareOpenGL];        isFullScreenPrepared = YES;    }    [mutex unlock];    return context;}// NOTE: This does not exist prior to Panther (10.3)- (void)prepareOpenGL{    long    swapInterval = 1;    [mutex lock];    [super prepareOpenGL];    [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];    [self initTextures];    /* Set GL_COLOR_BUFFER_BIT to black */    glClearColor (0.0, 0.0, 0.0, 0.0);    [mutex unlock];}- (void)reshape{    [mutex lock];    [super reshape];    if (initDone) {        [[self openGLContext] makeCurrentContext];                NSRect bounds = [self bounds];        glViewport(0, 0, bounds.size.width, bounds.size.height);        #ifdef LOG        NSLog(@"XineOpenGLView: Reshape: %x%x%x%x%x%x%x%x",              textureBuffer[0], textureBuffer[1], textureBuffer[2], textureBuffer[3],              textureBuffer[4], textureBuffer[5], textureBuffer[6], textureBuffer[7]);#endif    }    [mutex unlock];}- (void)update{    [mutex lock];    [super update];    [mutex unlock];}- (void)initTextures{    uint32_t    *p, *q, yuv;    [mutex lock];        /* Free previous texture if any */    if (texture) {        glDeleteTextures(1, &texture);        texture = 0;    }        if (!initialColorYUVIsSet && initialColor) {        initialColorYUV = NSColorToYUV(initialColor);        initialColorYUVIsSet = YES;    }    if (textureBuffer) {        textureBuffer = (char *)realloc(textureBuffer, videoSize.width * videoSize.height * 4);    }    else {        textureBuffer = (char *)malloc(videoSize.width * videoSize.height * 4);        // There _has_ to be a better way of doing this ...        yuv = OSSwapHostToBigInt32(initialColorYUV);        q = (uint32_t *)(char *)(textureBuffer + (int)(videoSize.width * videoSize.height * 4));        for (p = (uint32_t *)textureBuffer;  p < q;  *p++ = yuv);    }    /* Create textures */    glGenTextures(1, &texture);        glEnable(GL_TEXTURE_RECTANGLE_EXT);    glEnable(GL_UNPACK_CLIENT_STORAGE_APPLE);        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);    glPixelStorei(GL_UNPACK_ROW_LENGTH, videoSize.width);        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);        /* Use VRAM texturing */    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,                    GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE);        /* Tell the driver not to make a copy of the texture but to use        our buffer */    glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);        /* Linear interpolation */    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,                    GL_TEXTURE_MIN_FILTER, GL_LINEAR);    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,                    GL_TEXTURE_MAG_FILTER, GL_LINEAR);        /* I have no idea what this exactly does, but it seems to be        necessary for scaling */    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,                    GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,                    GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);        glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,                 videoSize.width, videoSize.height, 0, GL_YCBCR_422_APPLE,#if WORDS_BIGENDIAN                 GL_UNSIGNED_SHORT_8_8_APPLE,#else                 GL_UNSIGNED_SHORT_8_8_REV_APPLE,#endif                 textureBuffer);        initDone = YES;    [mutex unlock];#ifdef LOG    NSLog(@"XineOpenGLView: initTextures called: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",          textureBuffer[0], textureBuffer[1], textureBuffer[2], textureBuffer[3],          textureBuffer[4], textureBuffer[5], textureBuffer[6], textureBuffer[7]);#endif}- (void)updateTexture{    [mutex lock];    [[self openGLContext] makeCurrentContext];    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);    glPixelStorei(GL_UNPACK_ROW_LENGTH, videoSize.width);    // glTexSubImage2D is faster than glTexImage2D    // http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm    glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0,                    videoSize.width, videoSize.height, GL_YCBCR_422_APPLE,#if WORDS_BIG_ENDIAN                    GL_UNSIGNED_SHORT_8_8_APPLE,#else                    GL_UNSIGNED_SHORT_8_8_REV_APPLE,#endif                    textureBuffer);    [self setNeedsDisplay:YES];    [mutex unlock];}- (void)drawRect:(NSRect)rect{    [mutex lock];    if (initDone && texture) {        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);        glBegin(GL_QUADS);            glTexCoord2f(0.0,             0.0);               glVertex2f(-1.0,  1.0);   // top left            glTexCoord2f(0.0,             videoSize.height);  glVertex2f(-1.0, -1.0);   // bottom left            glTexCoord2f(videoSize.width, videoSize.height);  glVertex2f( 1.0, -1.0);   // bottom right            glTexCoord2f(videoSize.width, 0.0);               glVertex2f( 1.0,  1.0);   // top right        glEnd();        [[self openGLContext] flushBuffer];    }    [mutex unlock];}- (NSColor *)initialColor{    return initialColor;}- (void) setInitialColor:(NSColor *)color{    [initialColor autorelease];    initialColor = (color ? [color copy] : [[NSColor blackColor] retain]);}- (void)setNormalSize{    [mutex lock];    if (!isFullScreen) {        [self setViewSizeInMainThread:videoSize];    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?