CVOpenGLESTextureCache vs glTexSubImage2D on iOS

China☆狼群 提交于 2019-11-29 10:28:48

问题


My OpenGL app uses OpenGL to render a texture in full screen and updates part of it at regular intervals. So far, I've been using glTexImage2D to push my initial texture and then I update the dirty regions with glTexSubImage2D. To do that, I'm using single buffering. This works well.

I've seen that there might be another way to achieve the same thing using CVOpenGLESTextureCache. The textures held in the texture cache reference a CVPixelBuffer. I'd like to know if I can mutate these cached textures. I tried to recreate a CVOpenGLESTexture for each update but this decreases my frame rate dramatically (not surprising after all since I'm not specifying the dirty region anywhere). Maybe I totally misunderstood the use case for this texture cache.

Can someone provide some guidance?

UPDATE: Here is the code I'm using. The first update works fine. The subsequent updates don't (nothing happens). Between each update I modify the raw bitmap.

if (firstUpdate) {

    CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, ctx, NULL, &texCache);

    CVPixelBufferRef pixelBuffer;
    CVPixelBufferCreateWithBytes(NULL, width_, height_, kCVPixelFormatType_32BGRA, bitmap, width_*4, NULL, 0, NULL, &pixelBuffer);
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);

    CVOpenGLESTextureRef texture = NULL;
    CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, texCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);

    texture_[0] = CVOpenGLESTextureGetName(texture);

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}


CVOpenGLESTextureCacheFlush(texCache, 0);

if (firstUpdate) {
    glBindTexture(GL_TEXTURE_2D, texture_[0]);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

if (firstUpdate) {
    static const float textureVertices[] = {
        -1.0, -1.0,
        1.0, -1.0,
        -1.0, 1.0,
        1.0, 1.0
    };

    static const float textureCoords[] = {
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    glVertexPointer(2, GL_FLOAT, 0, &textureVertices[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
}

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

firstUpdate = false;

回答1:


I have been doing quite a bit of hacking with these texture APIs and I finally was able to produce a working example of writing to a texture via memory using the texture cache API. These APIs work on the iOS device but not on the simulator, so a special workaround was needed (basically just calling glTexSubImage2D() explicitly in the simulator). The code needed to double buffer the texture loading done in another thread to avoid updating while rendering was going on. The full source code and timing results are at opengl_write_texture_cache. The linked Xcode project decodes from PNGs and the performance on older iPhone hardware is a little poor as a result. But the code is free to do whatever you want with, so it should not be hard to adapt to some other pixel source. To only write a dirty region, only write to that portion of the memory buffer in the background thread.



来源:https://stackoverflow.com/questions/12813442/cvopenglestexturecache-vs-gltexsubimage2d-on-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!