Search code examples
objective-copenglquartz-2dsyphon

OpenGL Texture rendering as black


I'm using the Syphon framework to try and push frames of video from a server to a client application.

Syphon requires you to use OpenGL textures instead of normal images.

Because of this, I'm trying to render a CGImageRef as a texture and send it on to be published.

I'm creating my CGL context as so:

CGLPixelFormatAttribute attribs[13] = {
    kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core, // This sets the context to 3.2
    kCGLPFAColorSize,     (CGLPixelFormatAttribute)24,
    kCGLPFAAlphaSize,     (CGLPixelFormatAttribute)8,
    kCGLPFAAccelerated,
    kCGLPFADoubleBuffer,
    kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1,
    kCGLPFASamples,       (CGLPixelFormatAttribute)4,
    (CGLPixelFormatAttribute)0
};

CGLPixelFormatObj pix;
GLint npix;
CGLChoosePixelFormat(attribs, &pix, &npix);

CGLCreateContext(pix, 0, &_ctx);

I already have a CGImageRef that I know can be rendered properly as an NSImage.

I'm rendering the texture as so:

CGLLockContext(cgl_ctx);

if (_texture) {
    glDeleteTextures(1, &_texture);
}

int width = 1920;
int height = 1080;

GLubyte* imageData = malloc(width * height * 4);
CGContextRef imageContext = CGBitmapContextCreate(imageData, width, height, 8, width * 4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, width, height), image);
CGContextRelease(imageContext);

GLuint frameBuffer;
GLenum status;

glGenFramebuffersEXT(1, &frameBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBuffer);
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_TEXTURE_2D, imageData);

status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
    NSLog(@"OpenGL Error");
}

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

CGLUnlockContext(cgl_ctx);

The rendering code is in a different class, but the context should be passed through and is the same.

I've tried the advice in pretty much every other instance of this problem to no avail.


Solution

  • The second-to-last parameter in glTexImage2D is:

    type
    Specifies the data type of the pixel data. The following symbolic values are accepted: GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV.

    GL_TEXTURE_2D doesn't make sense there, it should be whatever the data type of elements of imageData is.

    You should also be checking your OpenGL errors with glGetError or ARB_debug_output. You would have immediately be shown what's wrong:

    Source:OpenGL   Type:Error  ID:5    Severity:High   Message:GL_INVALID_ENUM in glTexImage2D(incompatible format = GL_RGBA, type = GL_TEXTURE_2D)