質問の要約は次のとおりです。
一部のレイヤーの合成では、CGContext で OpenGL テクスチャをレンダリングする必要があります。それを行う最も速い方法は何ですか?
これまでの考え:
明らかに、renderInContext を呼び出しても OpenGL コンテンツはキャプチャされず、glReadPixels は遅すぎます。
一部の「コンテキスト」については、レイヤーのデリゲート クラスでこのメソッドを呼び出しています。
- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
CVOpenGLESTextureCache の使用を検討しましたが、それには追加のレンダリングが必要であり、レンダリング後に複雑な変換が必要になるようです。
これが私の(ひどい)実装です。
glBindRenderbuffer(GL_RENDERBUFFER, displayRenderbuffer);
NSInteger x = 0, y = 0, width = backingWidth, height = backingHeight;
NSInteger dataLength = width * height * 4;
GLubyte *data = (GLubyte *) malloc(dataLength * sizeof(GLubyte));
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
ref, NULL, true, kCGRenderingIntentDefault);
CGFloat scale = self.contentScaleFactor;
NSInteger widthInPoints, heightInPoints;
widthInPoints = width / scale;
heightInPoints = height / scale;
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextDrawImage(context, CGRectMake(0.0, 0.0, widthInPoints, heightInPoints), iref);
// Clean up
free(data);
CFRelease(ref);
CFRelease(colorspace);
CGImageRelease(iref);