I want to display a CIImage in a GLKView. The GLKView is in a containing view (the superview). I want the GLKView to render the image as aspect-fill. I want the GLKView to take up all the space of the containing UIView.
But not matter what I seem to do it comes out the wrong way. The result can be seen in the following image. The containing view has red background to make it easy to see. At the top we have the navigation bar and at the bottom is a toolbar with some grayed-out icons.
I simply have no idea why the GLKView won't fill up all of the containing view.
This is the code of the GLRenderer that does this
class GLImageRenderer {
private var glContext: EAGLContext
private var videoDisplayViewBounds: CGRect
private var videoDisplayView: GLKView
private var scale: CGFloat
private var renderContext: CIContext
init(superView: UIView) {
superView.backgroundColor = UIColor.red
glContext = EAGLContext(api: EAGLRenderingAPI.openGLES2)!
videoDisplayView = GLKView(frame: superView.frame, context: glContext)
videoDisplayView.contentScaleFactor = UIScreen.main.scale
videoDisplayView.contentMode = .scaleAspectFill
videoDisplayView.frame = superView.frame
videoDisplayView.transform = CGAffineTransform.init(rotationAngle: CGFloat.pi/2)
superView.addSubview(videoDisplayView)
superView.sendSubviewToBack(videoDisplayView)
renderContext = CIContext(eaglContext: videoDisplayView.context)
videoDisplayView.bindDrawable()
videoDisplayViewBounds = CGRect(x: 0,
y: 0,
width: videoDisplayView.drawableWidth,
height: videoDisplayView.drawableHeight)
scale = UIScreen.main.scale
}
func draw(ciimage: CIImage) {
let drawFrame = ciimage.extent
let imageAspectRatio = drawFrame.width / drawFrame.height
let viewAspectRatio = videoDisplayViewBounds.width / videoDisplayViewBounds.height
var newDrawFrame: CGRect
if imageAspectRatio > viewAspectRatio {
newDrawFrame = CGRect(x: drawFrame.minX + ((drawFrame.width - drawFrame.height * viewAspectRatio) / scale),
y: drawFrame.minY,
width: drawFrame.height * viewAspectRatio,
height: drawFrame.height)
} else {
newDrawFrame = CGRect(x: drawFrame.minX,
y: drawFrame.minY + ((drawFrame.height - drawFrame.width / viewAspectRatio) / scale),
width: drawFrame.width,
height: drawFrame.width / viewAspectRatio)
}
videoDisplayView.bindDrawable()
if videoDisplayView.context != EAGLContext.current() {
EAGLContext.setCurrent(videoDisplayView.context)
}
glClearColor(0.5, 0.5, 0.5, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
glEnable(GLenum(GL_BLEND))
glBlendFunc(GLenum(GL_ONE), GLenum(GL_ONE_MINUS_SRC_ALPHA))
renderContext.draw(ciimage, in:videoDisplayViewBounds, from: newDrawFrame)
videoDisplayView.display()
}
func close() {
videoDisplayView.removeFromSuperview()
}
}
As can be seen I set the content mode of the GLKView as aspect-fill, and the GLKView's frame is set to match the super view, but still it doesn't match up when rendering. I also tried different combinations of the CGRect arguments to the ciimage draw method, and although I obviously get some different results they all end up in the same place and never fills up the super view.
Any ideas?
