2011-08-01 16 views
7

Domanda semplice, è possibile caricare la trama in modo asincrono con iOS e OpenGL ES?OpenGL ES Async texture loading

Ecco il mio metodo di caricamento, chiamato in un thread separato:

//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); 

Se non spedizione OpenGL invita il thread principale, le mie trame wont essere visualizzati ...

Stessa domanda per il glDeleteTextures chiama ...

Qualche idea?

risposta

4

È necessario utilizzare lo stesso contesto sul thread in background che si sta utilizzando su quello principale. Per questo usare setCurrentContext:. Così il thread principale creare un nuovo thread (come ad esempio il modo più semplice) e passare contesto principale

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

E il codice di creazione:

-(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]; 
} 

Come opzione è anche possibile creare il nuovo contesto e condividere lo stesso EAGLSharegroup con quello principale.

+0

Mi chiedo se la chiamata a glBindTexture() utilizzata per creare la trama non interrompa alcun disegno che si sta eseguendo nel thread principale? Immagino che il gruppo di condivisione (= separati contesti gl) sia la strada da percorrere? –

+0

@ranReloaded Potrebbe interrompere il disegno se si sta distruggendo una trama attualmente utilizzata per il rendering. – Max

+1

No, ciò che intendevo è questo: nel momento in cui chiami glBindTexture() nel thread in background (quello che carica la texture) durante il processo di creazione della trama, qualsiasi (precedentemente creata, completamente caricata) trama che stavi usando per il disegno (nel thread principale) non viene associato (è possibile associare una trama alla volta a un determinato contesto, giusto?) –