Objective-C中的CaptureScreen在IMac上使用OpenGL

时间:2011-08-21 01:04:17

标签: objective-c opengl

我有一个多显示系统,27英寸(2560 x 1440)和Apple Cinema Display(1920 x 1200),配有ATI Radeon HD 5750 1024 MB显卡。我曾经能够使用我之前的iMac和Nvidia卡以及多显示系统捕捉屏幕截图。现在我得到一个OpenGL错误。

  

此GDB配置为“x86_64-apple-darwin”.tty / dev / ttys001   [切换到进程28434线程0x0] 2011-08-20 19:07:42.040   DetectObjectColor [28434:c03]无效的全屏drawable 2011-08-20   19:07:42.043 DetectObjectColor [28434:c03] *断言失败    - [OpenGLScreenReader readPartialScreenToBuffer:bufferBaseAddress:],   /Documents/Personal/Det​​ectObjectColor/OpenGLScreenReader.m:230   2011-08-20 19:07:42.043 DetectObjectColor [28434:c03] * 终止   应用程序由于未捕获的异常'NSInternalInconsistencyException',   原因:'OpenGL错误0x0506'

我从我的主程序中调用它:

OpenGLScreenReader *mOpenGLScreenReader;
mOpenGLScreenReader = [[OpenGLScreenReader alloc] init];
[mOpenGLScreenReader readRectScreen:CGRectMake(570, 265, 35, 800)];

这是我的初始化方法

-(id) init
{
    if (self = [super init])
    {
     // Create a full-screen OpenGL graphics context
     // Specify attributes of the GL graphics context
      NSOpenGLPixelFormatAttribute attributes[] = {

     NSOpenGLPFANoRecovery,
        NSOpenGLPFAFullScreen,
        NSOpenGLPFAScreenMask,
        CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
        (NSOpenGLPixelFormatAttribute) 0
    };

    NSOpenGLPixelFormat *glPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
    if (!glPixelFormat)
    {
        return nil;
    }

    // Create OpenGL context used to render
    mGLContext = [[[NSOpenGLContext alloc] initWithFormat:glPixelFormat shareContext:nil] autorelease];

    // Cleanup, pixel format object no longer needed
    [glPixelFormat release];
    if (!mGLContext)
    {
        [self release];
        return nil;
    }
    [mGLContext retain];

    // Set our context as the current OpenGL context
    [mGLContext makeCurrentContext];

    // Set full-screen mode
    [mGLContext setFullScreen];

    NSRect mainScreenRect = [[NSScreen mainScreen] frame];
    mWidth = mainScreenRect.size.width;
    mHeight = mainScreenRect.size.height;       
    mByteWidth = mWidth * 4;                // Assume 4 bytes/pixel for now
    mByteWidth = (mByteWidth + 3) & ~3;    // Align to 4 bytes      
    mData = malloc(mByteWidth * mHeight);
    NSAssert( mData != 0, @"malloc failed");        
  }
  return self;
}

这是我的readRectScreen方法,它在执行readPartialScreenToBuffer方法时给出了OpenGL的错误

- (void) readRectScreen:(CGRect) srcRect
{
    mWidth = srcRect.size.width;
mHeight = srcRect.size.height;
mByteWidth = mWidth * 4;                // Assume 4 bytes/pixel for now
mByteWidth = (mByteWidth + 3) & ~3;    // Align to 4 bytes

mData = malloc(mByteWidth * mHeight);

[self readPartialScreenToBuffer:srcRect bufferBaseAddress: mData];
}

- (void) readPartialScreenToBuffer: (CGRect) srcRect bufferBaseAddress: (void *) baseAddress
{
// select front buffer as our source for pixel data
    GLint width, height;
    width = srcRect.size.width;
    height = srcRect.size.height;
    glReadBuffer(GL_FRONT);
    //Read OpenGL context pixels directly.
    // For extra safety, save & restore OpenGL states that are changed
    glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
    glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

    //Read a block of pixels from the frame buffer
glReadPixels((GLint)srcRect.origin.x, (GLint)srcRect.origin.y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,baseAddress);

    glPopClientAttrib();

    //Check for OpenGL errors
    GLenum theError = GL_NO_ERROR;
    theError = glGetError();
    NSAssert1( theError == GL_NO_ERROR, @"OpenGL error 0x%04X", theError);
}

任何人都可以帮忙......我完全迷失了错误的位置。

2 个答案:

答案 0 :(得分:3)

我猜你的新电脑安装了Mac OS X 10.7(Lion)。 Lion不再允许这种屏幕捕获方法(读取前缓冲区)。应用程序必须迁移到CGDisplayCaptureImage()API,这是在10.6中引入的。

答案 1 :(得分:2)

您的问题似乎是,您没有/有一个有效的OpenGL上下文。但这不是你真正的问题:

OpenGL是一个绘图/渲染库。 glReadPixels 用于回读程序生成的图像。 OpenGL 不是一个通用的图形API (虽然有些/很多人对此感到困惑)。

有一段时间,人们可以利用OpenGL上下文,窗口和帧缓冲区之间的副作用来使用 glReadPixels 来截取屏幕截图。 在具有合成窗口管理器的现代系统上,这不再有效!

抱歉,你正在咆哮错误的树。