首页 文章

将IOSurfaces绘制到另一个IOSurface

提问于
浏览
2

如何将一系列IOSurfaces绘制到另一个IOSurfaces然后将其绘制到屏幕上?我在MultiGPU示例项目中玩过一些来自苹果的源代码,但我设法做的最好的是绘制白屏或获取大量文件并使应用程序崩溃 .

我对openGL很新,我不太了解framebuffers和纹理的绑定以及它们如何与IOSurfaces交互 .

这就是我必须从IOSurface创建一个纹理(直接来自Apple的源代码)

// Create an IOSurface backed texture
// Create an FBO using the name of this texture and bind the texture to the color attachment of the FBO
- (GLuint)setupIOSurfaceTexture:(IOSurfaceRef)ioSurfaceBuffer {
    GLuint name;
    CGLContextObj cgl_ctx = (CGLContextObj)[[self openGLContext] CGLContextObj];

    glGenTextures(1, &name);

    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, name);
    CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 512, 512, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                ioSurfaceBuffer, 0);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    // Generate an FBO using the same name with the same texture bound to it as a render target.

    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, name);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, name, 0);

    if(!_depthBufferName) {
        glGenRenderbuffersEXT(1, &_depthBufferName);
        glRenderbufferStorageEXT(GL_TEXTURE_RECTANGLE_EXT, GL_DEPTH, 512, 512);
    }
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_EXT, _depthBufferName);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    return name;
}

我有这段代码将表面绘制到屏幕上 . (也来自Apple的来源)

// Fill the view with the IOSurface backed texture 
- (void)textureFromCurrentIOSurface {
    NSRect bounds = [self bounds];
    CGLContextObj cgl_ctx = (CGLContextObj)[[self openGLContext] CGLContextObj];

    // Render quad from our iosurface texture
    glViewport(0, 0, (GLint)bounds.size.width, (GLint)bounds.size.height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();   
    glOrtho(0.0, (GLfloat)bounds.size.width, 0.0f, (GLfloat)bounds.size.height, -1.0f, 1.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, [[NSApp delegate] currentTextureName]); // Grab the texture from the delegate
    glEnable(GL_TEXTURE_RECTANGLE_EXT);
    glTexEnvi(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    glBegin(GL_QUADS);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    glTexCoord2f(0.0f, 0.0f);
    glVertex2f(0.0f, 0.0f);

    glTexCoord2f(512.0f, 0.0f);
    glVertex2f((GLfloat)bounds.size.width, 0.0f);

    glTexCoord2f(512.0f, 512.0f);
    glVertex2f((GLfloat)bounds.size.width, (GLfloat)bounds.size.height);

    glTexCoord2f(0.0f, 512.0f);
    glVertex2f(0.0f, (GLfloat)bounds.size.height);

    glEnd();

    glDisable(GL_TEXTURE_RECTANGLE_EXT);
}

只有一个IOSurface被绘制到屏幕上,这很好 . 我错过了将IOSurface画给另一个人?

假设我有纹理A,B,C和D我想:

-Draw A到特定区域的C,

  • 将B绘制到不同区域的C上(可能与A重叠),
    -Draw C到屏幕 .

1 回答

  • 2

    我使用以下代码解决了这个问题,但是在绘制之前缩放IOSurface存在一些小问题 .

    - (void)renderIOSurface:(IOSurfaceRef)surface toBuffer:(GLuint)buffer atPoint:(CGPoint)point withSize:(CGSize)size {
    CGLContextObj cgl_ctx = (CGLContextObj)[[self openGLContext] CGLContextObj];
    
    // Bind framebuffer
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buffer);
    
    glViewport(0, 0, TEXWIDE, TEXHIGH);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0.0, TEXWIDE, 0.0, TEXHIGH, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    
    GLsizei sH  = (GLsizei)IOSurfaceGetHeight(surface);
    GLsizei sW   = (GLsizei)IOSurfaceGetWidth(surface);
    
    // Create texture
    GLuint name;
    glGenTextures(1, &name);
    glEnable(GL_TEXTURE_RECTANGLE_EXT);
    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, name);
    CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, sW, sH, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    //  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
    
    //glDisable(GL_BLEND);
    
    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(1.0f, 1.0f, 1.0f, 1.0f);
    
    glTexCoord2f(0.0f, 0.0f);
    glVertex2f(point.x, point.y);
    
    glTexCoord2f(sW, 0.0f);
    glVertex2f(point.x + size.width, point.y);
    
    glTexCoord2f(sW, sH);
    glVertex2f(point.x + size.width, point.y + size.height);
    
    glTexCoord2f(0.0f, sH);
    glVertex2f(point.x, point.y + size.height);
    
    glEnd();
    
    //glDisable(GL_TEXTURE_RECTANGLE_EXT);
    
    // Bindback to normal
    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    
    // Delete the name texture
    glDeleteTextures(1, &name);
    
    //  [[self openGLContext] flushBuffer];
    // This flush is necessary to ensure proper behavior if the MT engine is enabled.
    //  glFlush();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glFlush();
    }
    

相关问题