2011-08-01 4 views
7

Простой вопрос: можно ли асинхронно загружать текстуру с iOS и OpenGL ES?OpenGL ES Async texture loading

Вот мой метод загрузки, названный в отдельном потоке:

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

Если я не отправлять OpenGL вызовов в основном потоке, мои текстуры обыкновение отображаться ...

Тот же вопрос для вызова glDeleteTextures ...

Любая идея?

ответ

4

Вам нужно использовать тот же контекст в фоновом потоке, который вы используете на основном. Для этого используйте setCurrentContext:. Так что на главном потоке создать новую нить (в качестве примера самый простой способ) и передать основной контекст

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

И код создания:

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

В качестве опции можно также создать новый контекст и поделитесь тем же EAGLSharegroup с основным.

+0

Интересно, не вызовет ли этот вызов glBindTexture() для создания текстуры ни один чертеж, который вы можете выполнять в основном потоке? Я думаю, что общая группа (= отдельные глобальные контексты) - это способ пойти? –

+0

@ranReloaded Это может привести к нарушению рисования, если вы уничтожаете текстуру, которая в настоящее время используется для рендеринга. – Max

+1

Нет, я имел в виду следующее: в тот момент, когда вы вызываете glBindTexture() в фоновом потоке (который загружает текстуру) во время процесса создания текстуры, независимо от (ранее созданной, полностью загруженной) текстуры, которую вы в настоящее время используете для рисования (в основном потоке) становится несвязанным (вы можете привязывать только одну текстуру одновременно к любому заданному контексту, верно?) –

Смежные вопросы