2011-08-01 14 views
7

Pregunta simple, ¿es posible cargar texturas de forma asíncrona con iOS y OpenGL ES?OpenGL ES Async texture loading

Aquí es mi método de carga, llamada en un hilo separado:

//Image size 
GLuint width = CGImageGetWidth(image.CGImage); 
GLuint height = CGImageGetHeight(image.CGImage); 

//Create context 
void *imageData = malloc(height * width * 4); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
CGColorSpaceRelease(colorSpace); 

//Prepare image 
CGContextClearRect(context, CGRectMake(0, 0, width, height)); 
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage); 

//Dispatch OpenGL stuff on main thread 
dispatch_sync(dispatch_get_main_queue(), ^{ 
    //Bind texture 
    glBindTexture(GL_TEXTURE_2D, name); 

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
}); 

//Release 
CGContextRelease(context); 
free(imageData); 

Si no distribuyen OpenGL pide al hilo principal, mis texturas suele ser exhibidos ...

La misma pregunta para la llamada glDeleteTextures ...

¿Alguna idea?

Respuesta

4

Debe usar el mismo contexto en la cadena de fondo que está utilizando en la principal. Para este uso, setCurrentContext:. Así que el hilo principal crear un nuevo hilo (como un ejemplo de la forma más sencilla) y pasar contexto principal

[self performSelectorInBackground: @selector(loadTextureWithContext:) withObject: [EAGLContext currentContext]]; 

Y el código de creación:

-(void) loadTextureWithContext:(EAGLContext*) main_context { 
    [EAGLContext setCurrentContext: main_context]; 

    //Image size 
    GLuint width = CGImageGetWidth(image.CGImage); 
    GLuint height = CGImageGetHeight(image.CGImage); 

    //Create context 
    void *imageData = malloc(height * width * 4); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
    CGColorSpaceRelease(colorSpace); 

    //Prepare image 
    CGContextClearRect(context, CGRectMake(0, 0, width, height)); 
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage); 

    //Bind texture 
    glBindTexture(GL_TEXTURE_2D, name); 

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    //Release 
    CGContextRelease(context); 
    free(imageData); 

    [EAGLContext setCurrentContext: nil]; 
} 

Como opción también se puede crear el nuevo contexto y comparte el mismo EAGLSharegroup con el principal.

+0

Me pregunto si la llamada glBindTexture() utilizada para crear la textura no interrumpirá ningún dibujo que pueda estar realizando en el hilo principal. Supongo que compartir grupo (= contextos GL separados) es el camino a seguir. –

+0

@ranReloaded Podría interrumpir el dibujo si está destruyendo una textura que se utiliza actualmente para la representación. – Max

+1

No, lo que quise decir es esto: el momento en que llamas glBindTexture() en el hilo de fondo (el que carga la textura) durante el proceso de creación de textura, cualquier textura (previamente creada, completamente cargada) que estabas usando para dibujar (en el hilo principal) se desata (solo se puede enlazar una textura a la vez con un contexto dado, ¿no?) –