2014-02-27 52 views
0

我有一个使用OpenGL成功绘制的OpenGL上下文。在OpenGL上下文中绘制一个IOSurface

我需要在此上下文中绘制一个IOSurface的特定矩形。

在10.8上做到这一点的最佳方法是什么?

: 我知道如何使用CoreImage做到这一点的10.9(由createing从IOSurface一个CIImage,并与[CIContext drawImage:inRect:fromRect]呈现它)。 然而,这在10.8(我的图像的每个原始图像显示不同的偏移量,并且图像对角线扭曲)上效果不佳。

编辑:下面是在10.9,但并不适用于10.8的代码:

CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); 

CIImage* ciImage = [[CIImage alloc] initWithIOSurface:surface plane:0 format:kCVPixelFormatType_32BGRA options:@{kCIImageColorSpace : (__bridge id)colorSpace}]; 
NSRect flippedFromRect = fromRect; 
// Flip rect before passing to CoreImage: 
{ 
    flippedFromRect.origin.y = IOSurfaceGetHeight(surface) - fromRect.origin.y - fromRect.size.height; 
} 
[ciContext drawImage:ciImage inRect:inRect fromRect:flippedFromRect]; 


CGColorSpaceRelease(colorSpace); 
+0

斜失真?你不是偶然使用RGB图像吗?这让我想起了很多与数据对齐的问题...通常像素必须在32位边界上对齐,24位图像格式是司机试图最大程度地隐藏起来的一堆烟雾和镜子。如果在读取/上传像素数据时没有获得正确的像素包/解包状态,幕后的魔法就不再是魔法了。这也适用于某些图像文件格式,例如DIB('.bmp') - 每条扫描线都对齐到32位(DWORD)边界。 –

+0

具有很多意义,但我使用'BGRA'来创建IOSurface,并且我找不到对齐/像素格式错误,或者为什么它在10.8上无法正常工作。这就是为什么我试图使用较低级别的API。 我的NSOpenGLPixelFormat attributs包括{NSOpenGLPFAColorSize,32,...},它在10.9上可以找到。我使用CIImage将JPG渲染到IOSurface,在OpenCL中将其处理到另一个表面,这是我当前使用Core Image呈现的表面。 –

+0

你可以显示你用来在GL中绘制图像的代码吗?我不确定是否使用Core Image为表面提供OpenGL纹理句柄,或者如果您尝试使用诸如'glTexImage2D(...)之类的东西上传图像数据...)'添加了与之相关的像素传输状态/格式转换。 –

回答

1

这里是用一个OpenGL纹理包裹IOSurface并绘制纹理到屏幕的解决方案。这个假定与[CIContext render:toIOSurface:bounds:colorSpace:]类似的API,但是垂直翻转的OpenGL坐标系。

// Draw surface on OpenGL context 
    { 
    // Enable the rectangle texture extenstion 
    glEnable(GL_TEXTURE_RECTANGLE_EXT); 

    // 1. Create a texture from the IOSurface 
    GLuint name; 
    { 
     CGLContextObj cgl_ctx = ... 

     glGenTextures(1, &name); 
     GLsizei surface_w = (GLsizei)IOSurfaceGetWidth(surface); 
     GLsizei surface_h = (GLsizei)IOSurfaceGetHeight(surface); 

     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, name); 

     CGLError cglError = 
     CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, surface_w, surface_h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0); 

     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);   
    } 

    // 2. Draw the texture to the current OpenGL context 
    { 
     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, name); 
     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 

     glBegin(GL_QUADS); 

     glColor4f(0.f, 0.f, 1.0f, 1.0f); 
     glTexCoord2f( (float)NSMinX(fromRect), (float)(NSMinY(fromRect))); 
     glVertex2f( (float)NSMinX(inRect),  (float)(NSMinY(inRect))); 

     glTexCoord2f( (float)NSMaxX(fromRect), (float)NSMinY(fromRect)); 
     glVertex2f( (float)NSMaxX(inRect),  (float)NSMinY(inRect)); 

     glTexCoord2f( (float)NSMaxX(fromRect), (float)NSMaxY(fromRect)); 
     glVertex2f( (float)NSMaxX(inRect),  (float)NSMaxY(inRect)); 

     glTexCoord2f( (float)NSMinX(fromRect), (float)NSMaxY(fromRect)); 
     glVertex2f( (float)NSMinX(inRect),  (float)NSMaxY(inRect)); 

     glEnd(); 

     glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); 
    } 
    glDeleteTextures(1, &name); 
    } 

如果您需要在显示器的颜色配置文件来绘制,你可以显式调用的ColorSync,并将它传递源轮廓和目标轮廓。它会返回给你一个“配方”来执行颜色校正。该配方实际上具有线性化,颜色转换(3x3转换矩阵)和伽马。

FragmentInfo = ColorSyncTransformCopyProperty (transform, kColorSyncTransformFullConversionData, NULL); 

如果你喜欢,你可以将所有这些操作组合成一个3D查找表。这实际上是许多OS X框架和应用程序的颜色管理中发生的事情。

参考文献:

  1. Apple TextureUpload sample code

  2. Draw IOSurfaces to another IOSurface

  3. OpenGL Options for Advanced Color Management