문제

I have an OpenGL context on which I draw successfully using OpenGL.

I need to draw a specific rectangle of an IOSurface to this context.

What is the best way to do this on 10.8?

NOTE: I know how to do this on 10.9 using CoreImage (by createing a CIImage from the IOSurface, and render it with [CIContext drawImage:inRect:fromRect]). However, this does not work well for me on 10.8 (each raw of the image is displayed with a different offset, and the image is distorted diagonally).

Edit: Here is the code that works on 10.9 but not on 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);
도움이 되었습니까?

해결책

Here is the solution by wrapping the IOSurface with an OpenGL texture and draw the texture to the screen. This assumes a similar API to [CIContext render:toIOSurface:bounds:colorSpace:] but a vertically flipped OpenGL coordinate system.

  // 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);
  }

If you need to draw in the display's color profile, you can explicitly call ColorSync and pass it your source profile and destination profile. It will return to you a “recipe” to perform the color correction. That recipe actually has a linearization, a color conversion (a 3x3 conversion matrix) and a gamma.

FragmentInfo = ColorSyncTransformCopyProperty (transform, kColorSyncTransformFullConversionData, NULL);

If you like, you can combine all those operations into a 3D lookup table. That's actually what happens in the color management of many of the OS X frameworks and applications.

References:

  1. Apple TextureUpload sample code

  2. Draw IOSurfaces to another IOSurface

  3. OpenGL Options for Advanced Color Management

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top