Alatriste
Alatriste

Reputation: 567

Mac OS OpenGL screen grab

I'm trying capture mac os desktop by OpenGL i.e GL desktop grabbing.

CGContextRef bitmap;
CGImageRef image;
void * data;
long bytewidth;
GLint width, height;
long bytes;
CGColorSpaceRef cSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGLContextObj    glContextObj;
CGLPixelFormatObj pixelFormatObj ;
GLint            numPixelFormats ;

int attribs[] =
{
    kCGLPFAFullScreen,
    kCGLPFADisplayMask,
    NULL,
    kCGLPFAColorSize, 24,
    kCGLPFAAlphaSize, 0,
    kCGLPFADepthSize, 32,
    NULL
};

CGDirectDisplayID display;
if(display == kCGNullDirectDisplay)
{
    display = CGMainDisplayID();
}

attribs[2] = CGDisplayIDToOpenGLDisplayMask(display);

CGLChoosePixelFormat( (CGLPixelFormatAttribute*) attribs, &pixelFormatObj, &numPixelFormats );
if ( pixelFormatObj == NULL )    // No full screen context support
{
    attribs[10] = NULL;
    CGLChoosePixelFormat( (CGLPixelFormatAttribute*) attribs, &pixelFormatObj, &numPixelFormats );
    if (pixelFormatObj == NULL)
    {
        return;
    }
}
CGLCreateContext( pixelFormatObj, NULL, &glContextObj ) ;
CGLDestroyPixelFormat( pixelFormatObj ) ;
if ( glContextObj == NULL )
{
   return;
}

CGLSetCurrentContext( glContextObj ) ;
CGLSetFullScreen( glContextObj ) ;

glReadBuffer(GL_FRONT);

width = scrWidth;
height = srcHeight;

bytewidth = width * 4; // Assume 4 bytes/pixel for now
bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
bytes = bytewidth * height; // width * height

data = malloc(height * bytewidth);
if ( data == NULL )
{
    CGLSetCurrentContext( NULL );
    CGLClearDrawable( glContextObj ); // disassociate from full screen
    CGLDestroyContext( glContextObj ); // and destroy the context
    return;
}
bitmap = CGBitmapContextCreate(data, width, height, 8, bytewidth,
                               cSpace, kCGImageAlphaNoneSkipFirst /* XRGB */);
CFRelease(cSpace);

glFinish(); 
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

glReadPixels(0, 0, width, height,
             GL_RGB,
  #ifdef __BIG_ENDIAN__
             GL_UNSIGNED_BYTE, // for PPC
  #else
             GL_UNSIGNED_BYTE, // for Intel!
  #endif
             data);

swizzleBitmap(data, bytewidth, height);

image = CGBitmapContextCreateImage(bitmap);

CFRelease(bitmap);
free(data);

CGLSetCurrentContext( NULL );
CGLClearDrawable( glContextObj );
CGLDestroyContext( glContextObj );

But I'm getting black images. I'm using 10.10.3 OS X Yosemite . What the problem can be here? maybe problem is in mac os version?

I'm writing pixel data into the file by glReadPixels but without result, again black images.

Upvotes: 1

Views: 776

Answers (1)

datenwolf
datenwolf

Reputation: 162164

OpenGL can not be used reliably for screen capturing. The "OpenGL screen capture examples" that do the fullscreen-window-glReadPixels thing rely on undefined behavior of the underlying graphics system. Namely that windows share the screen framebuffer and that a newly created window without a erasure brush will "inherit" the contents of the screen where it was created.

On modern graphics systems all these assumptions fail:

  • Windows don't share the screen framebuffer
  • Windows always are initialized with some clearing brush
  • Windows are composited into the final desktop appearance

Upvotes: 3

Related Questions