为什么在用于 OpenGL 纹理的 CGContext 上调用绘制函数时会出现 BAD_ACCESS 错误?

Why am I getting a BAD_ACCESS fault when calling draw functions on a CGContext used for an OpenGL texture?

我正在尝试使用 Core Graphics 创建 OpenGL 纹理。我的代码设置在 prepareOpenGL() 中。在绘制初始化的 CGContext 时,出现 EXC_BAD_ACCESS 错误。但是,当我在 LLDB 中 po 上下文时(po context!,见下文),我得到一个包含所有 CGContext 信息的地址。我也试过通过 LLDB 调用表达式,输出是 nil。地址清理器、线程清理器和僵尸程序是非暴露的。我的问题是,当 Optional<CGContext> 不是 nil 时,为什么 CGContext 被声明为 nil,EXC_BAD_ACCESS?我曾尝试在 drawRect(_:) 中调用此代码,但我得到了相同的结果。

import Cocoa
import CoreGraphics
import OpenGL.GL3

class MyView: NSOpenGLView {
    var textureTBO: GLuint = 0

    override func prepareOpenGL() {
        let bitmapRows = 10
        let bitmapColumns = 10
        let floatsPerPoint = 4
        var bitmapBuffer = UnsafeMutablePointer<CGFloat>.allocate(capacity: bitmapRows * bitmapColumns * floatsPerPoint)

        if let context = CGContext(data: &bitmapBuffer,
                                width: bitmapColumns,
                                height: bitmapRows,
                                bitsPerComponent: 8,
                                bytesPerRow: bitmapColumns * floatsPerPixel,
                                space: CGColorSpaceCreateDeviceRGB(),
                                bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) {
            context.setFillColor(red: 0, green: 0, blue: 1, alpha: 0.5)
            context.fill(CGRect(x: 0, y: 0, width: 5, height: 5))       //=>  EXC_BAD_ACCESS, code=2
            context.setFillColor(red: 1, green: 0, blue: 1, alpha: 0.5)
            context.fill(CGRect(x: 5, y: 5, width: 5, height: 5))
            context.setFillColor(red: 0, green: 1, blue: 0, alpha: 0.5)
            context.fill(CGRect(x: 0, y: 5, width: 5, height: 5))
            context.setFillColor(red: 0.5, green: 0, blue: 0.5, alpha: 0.5)
            context.fill(CGRect(x: 5, y: 0, width: 5, height: 5))
        
            glGenTextures(1, &textureTBO)
            glBindTexture(GLenum(GL_TEXTURE_2D), textureTBO)
            glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR)
            glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR)
            glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_REPEAT)
            glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_REPEAT)
        }

        glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GLint(GL_RGB), 256, 256, 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_INT), &bitmapBuffer)

        bitmapBuffer.deallocate()
    }
}

LLDB 输出 - 可选不为零

(lldb) po context!
<CGContext 0x7b3000000300> (kCGContextTypeBitmap)
    <<CGColorSpace 0x7b1800002280> (kCGColorSpaceDeviceRGB)>
        width = 256, height = 256, bpc = 8, bpp = 32, row bytes = 2048 
        kCGImageAlphaNoneSkipLast | 0 (default byte order)

LLDB 输出 - 这是否告诉我无法设置颜色,因为上下文实际上是 nil?

(lldb) expression context?.setFillColor(red: 0, green: 0, blue: 1, alpha: 0.5)
(Void?) $R4 = nil

LLDB 输出 - 徒劳的练习:做同样的事情并期待不同的结果,哈哈

(lldb) expression context?.fill(CGRect(x: 0, y: 0, width: 5, height: 5))
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x7b08000c7ff0).
The process has been returned to the state before expression evaluation.

我发现this answer好像可以做到这一点。我很欣赏你的想法,谢谢!

data: &bitmapBuffer是指向缓冲区的指针。将其替换为 data: bitmapBuffer.

与崩溃无关,但每个组件 8 位适合 UInt8:

var bitmapBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bitmapRows * bitmapColumns * floatsPerPoint)