2010-03-07 35 views
10

Tôi có một "trình kết xuất phần mềm" mà tôi đang chuyển từ PC sang iPhone. cách nhanh nhất để tự cập nhật màn hình bằng bộ đệm pixel trên iphone là gì? ví dụ trong các cửa sổ chức năng nhanh nhất mà tôi đã tìm thấy là SetDIBitsToDevice.Cách nhanh nhất để vẽ bộ đệm màn hình trên iphone

Tôi không biết nhiều về iphone, hoặc các thư viện, và có vẻ như có rất nhiều lớp và các loại khác nhau của các yếu tố giao diện người dùng, vì vậy tôi có thể cần rất nhiều lời giải thích ...

cho bây giờ Tôi chỉ sẽ liên tục cập nhật một kết cấu trong opengl và đưa nó lên màn hình, tôi rất nghi ngờ rằng đây sẽ là cách tốt nhất để làm điều đó.

UPDATE:

Tôi đã thử phương pháp kết cấu màn hình có kích thước OpenGL:

tôi đã 17fps ...

tôi đã sử dụng một kết cấu 512x512 (vì nó cần phải được một sức mạnh của hai)

chỉ là tiếng gọi của

glTexSubImage2D(GL_TEXTURE_2D,0,0,0,512,512,GL_RGBA,GL_UNSIGNED_BYTE, baseWindowGUI->GetBuffer()); 

dường như khá nhiều lại tài trợ cho TẤT CẢ sự chậm lại.

nhận xét nó ra, và để lại trong tất cả phần mềm của tôi hiển thị mã GUI và kết xuất của kết cấu hiện không cập nhật, kết quả là 60fps, sử dụng trình kết xuất 30% và không có đột biến đáng chú ý từ cpu.

lưu ý rằng GetBuffer() đơn giản trả về con trỏ cho phần mềm backbuffer của hệ thống GUI, không có re-gigging hoặc thay đổi kích thước của bộ đệm trong anyway, nó là đúng kích cỡ và định dạng cho kết cấu, vì vậy tôi khá chắc chắn sự chậm lại không liên quan gì đến trình kết xuất phần mềm, đó là tin tốt, có vẻ như nếu tôi có thể tìm cách cập nhật màn hình ở mức 60, việc hiển thị phần mềm sẽ hoạt động trong thời gian này.

Tôi đã thử thực hiện cuộc gọi kết cấu cập nhật với 512,320 thay vì 512,512 điều này thậm chí còn chậm hơn ... chạy ở tốc độ 10 khung hình/giây, đồng thời cho biết việc sử dụng kết xuất chỉ là 5% và tất cả thời gian bị lãng phí trong cuộc gọi vào Untwiddle32bpp bên trong openGLES.

Tôi có thể thay đổi phần mềm của mình để hiển thị tự nhiên thành bất kỳ định dạng pixle nào, nếu nó dẫn đến một blit trực tiếp hơn.

FYI, thử nghiệm trên một 2.2.1 G2 ipod touch (vì vậy giống như một Iphone 3G trên steroid)

UPDATE 2:

Tôi vừa writting phương pháp CoreAnimation/Graphics xong, nó có vẻ tốt, nhưng tôi hơi lo lắng về cách nó cập nhật màn hình mỗi khung hình, về cơ bản bỏ qua CGImage cũ, tạo một thương hiệu mới ... kiểm tra nó trong 'someRandomFunction' bên dưới: là cách nhanh nhất để cập nhật hình ảnh? Mọi sự trợ giúp sẽ rất được trân trọng.

// 
// catestAppDelegate.m 
// catest 
// 
// Created by User on 3/14/10. 
// Copyright __MyCompanyName__ 2010. All rights reserved. 
// 




#import "catestAppDelegate.h" 
#import "catestViewController.h" 
#import "QuartzCore/QuartzCore.h" 

const void* GetBytePointer(void* info) 
{ 
    // this is currently only called once 
    return info; // info is a pointer to the buffer 
} 

void ReleaseBytePointer(void*info, const void* pointer) 
{ 
    // don't care, just using the one static buffer at the moment 
} 


size_t GetBytesAtPosition(void* info, void* buffer, off_t position, size_t count) 
{ 
    // I don't think this ever gets called 
    memcpy(buffer, ((char*)info) + position, count); 
    return count; 
} 

CGDataProviderDirectCallbacks providerCallbacks = 
{ 0, GetBytePointer, ReleaseBytePointer, GetBytesAtPosition, 0 }; 


static CGImageRef cgIm; 

static CGDataProviderRef dataProvider; 
unsigned char* imageData; 
const size_t imageDataSize = 320 * 480 * 4; 
NSTimer *animationTimer; 
NSTimeInterval animationInterval= 1.0f/60.0f; 


@implementation catestAppDelegate 

@synthesize window; 
@synthesize viewController; 


- (void)applicationDidFinishLaunching:(UIApplication *)application {  


    [window makeKeyAndVisible]; 


    const size_t byteRowSize = 320 * 4; 
    imageData = malloc(imageDataSize); 

    for(int i=0;i<imageDataSize/4;i++) 
      ((unsigned int*)imageData)[i] = 0xFFFF00FF; // just set it to some random init color, currently yellow 


    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    dataProvider = 
    CGDataProviderCreateDirect(imageData, imageDataSize, 
           &providerCallbacks); // currently global 

    cgIm = CGImageCreate 
    (320, 480, 
    8, 32, 320*4, colorSpace, 
    kCGImageAlphaNone | kCGBitmapByteOrder32Little, 
    dataProvider, 0, false, kCGRenderingIntentDefault); // also global, probably doesn't need to be 

    self.window.layer.contents = cgIm; // set the UIWindow's CALayer's contents to the image, yay works! 

    // CGImageRelease(cgIm); // we should do this at some stage... 
    // CGDataProviderRelease(dataProvider); 

    animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(someRandomFunction) userInfo:nil repeats:YES]; 
    // set up a timer in the attempt to update the image 

} 
float col = 0; 

-(void)someRandomFunction 
{ 
    // update the original buffer 
    for(int i=0;i<imageDataSize;i++) 
     imageData[i] = (unsigned char)(int)col; 

    col+=256.0f/60.0f; 

    // and currently the only way I know how to apply that buffer update to the screen is to 
    // create a new image and bind it to the layer...??? 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    cgIm = CGImageCreate 
    (320, 480, 
    8, 32, 320*4, colorSpace, 
    kCGImageAlphaNone | kCGBitmapByteOrder32Little, 
    dataProvider, 0, false, kCGRenderingIntentDefault); 

    CGColorSpaceRelease(colorSpace); 

    self.window.layer.contents = cgIm; 

    // and that currently works, updating the screen, but i don't know how well it runs... 
} 


- (void)dealloc { 
    [viewController release]; 
    [window release]; 
    [super dealloc]; 
} 


@end 
+0

Tôi cũng gặp vấn đề này, là giải pháp duy nhất để tạo và tiêu diệt một khung hình CGImage? (đã thử điều này và chậm hơn so với glTexsubimage). Dường như toàn bộ điểm của nhà cung cấp trực tiếp là nó nên trỏ đến bộ đệm đó vì vậy nếu tôi thay đổi nó, hình ảnh được cập nhật. Bất kỳ trợ giúp về điều này? –

+0

Tôi nghĩ rằng điểm của việc sử dụng CGDataProviderCreateDirect là truy cập trực tiếp vào một bộ đệm pixel, làm mới bằng cách sử dụng CADisplayLink. Thật không may, điều này là khủng khiếp chậm. Bất kỳ cách giải quyết nào được phát hiện? – aoakenfo

Trả lời

11

nhanh nhất App Store đã được phê duyệt cách để làm CPU chỉ đồ họa 2D là tạo ra một CGImage được hỗ trợ bởi một bộ đệm sử dụng CGDataProviderCreateDirect và gán đến một contents tài sản CALayer 's.

Để có kết quả tốt nhất, hãy sử dụng các loại bitmap kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little hoặc kCGImageAlphaNone | kCGBitmapByteOrder32Little bitmap và bộ đệm kép sao cho màn hình không bao giờ ở trạng thái không nhất quán.

chỉnh sửa: điều này phải nhanh hơn bản vẽ cho kết cấu OpenGL theo lý thuyết, nhưng như mọi khi, hồ sơ phải chắc chắn.

edit2: CADisplayLink là lớp hữu ích cho dù bạn sử dụng phương pháp tổng hợp nào.

+0

Điều này có đủ nhanh để thực hiện video 24 fps không? –

+0

@ St3fan: Tôi hy vọng nó đủ nhanh để làm 60fps ít nhất! Tôi bắt đầu có cảm giác rằng Api và hệ điều hành của iPhone thậm chí còn cồng kềnh hơn Windows máy tính để bàn! @rpetrich, cảm ơn, tôi sẽ dùng thử. Tôi hầu như không biết bất cứ điều gì về iphone dev, giống như các công cụ GUI vv, vì vậy nó có thể đưa tôi một thời gian, bạn có thể giới thiệu một mẫu tốt để sử dụng để bắt đầu? Tôi chỉ sử dụng GL mở. – matt

+0

Matt các API iPhone cực kỳ tốt đẹp so với Win32. Một số điều đơn giản là không thể với mã Cocoa cấp cao hơn. Gửi một lỗi reuqest với Apple nếu bạn nghĩ rằng điều này cần một Cocoa API đẹp hơn. –

3

Cách nhanh nhất là sử dụng IOFrameBuffer/IOSurface, là khung riêng tư.

Vì vậy, OpenGL có vẻ là cách duy nhất có thể cho các ứng dụng AppStore.

+0

Tôi đã cập nhật câu hỏi với kết quả từ phương pháp opengl, không tốt. – matt

1

Có lẽ bạn có thể tóm tắt các phương pháp được sử dụng trong trình kết xuất phần mềm cho trình đổ bóng GPU ... có thể có hiệu suất tốt hơn. Bạn cần gửi dữ liệu "video" được mã hóa dưới dạng kết cấu.

+0

đây là một ý tưởng tốt, không phải cho trường hợp của tôi không may, nhưng chắc chắn cho những người khác. – matt

0

Phương pháp nhanh hơn cả hai CGDataProviderglTexSubImage là sử dụng CVOpenGLESTextureCache. CVOpenGLESTextureCache cho phép bạn trực tiếp sửa đổi kết cấu OpenGL trong bộ nhớ đồ họa mà không cần tải lên lại.

tôi đã sử dụng nó cho một cái nhìn hình ảnh động nhanh chóng, bạn có thể xem tại đây:

https://github.com/justinmeiners/image-sequence-streaming

Đó là một chút khó khăn để sử dụng và tôi đi qua nó sau khi yêu cầu câu hỏi của riêng tôi về chủ đề này: How to directly update pixels - with CGImage and direct CGDataProvider

1

Chỉ để gửi bình luận của tôi cho câu trả lời của @ rpetrich dưới dạng câu trả lời, tôi sẽ nói trong các bài kiểm tra của mình tôi thấy OpenGL là cách nhanh nhất. Tôi đã thực hiện một đối tượng đơn giản (UIView phân lớp) được gọi là EEPixelViewer mà thực hiện điều này đủ rộng mà nó sẽ làm việc cho hầu hết mọi người tôi nghĩ.

Sử dụng OpenGL để đẩy pixel ở nhiều định dạng khác nhau (định dạng 24bpp RGB, 32 bit RGBA và một số định dạng YpCbCr) đến màn hình hiệu quả nhất có thể. Giải pháp đạt được 60fps cho hầu hết các định dạng pixel trên hầu hết mọi thiết bị iOS, bao gồm cả các thiết bị cũ hơn. Cách sử dụng siêu đơn giản và không đòi hỏi kiến ​​thức OpenGL:

pixelViewer.pixelFormat = kCVPixelFormatType_32RGBA; 
pixelViewer.sourceImageSize = CGSizeMake(1024, 768); 
EEPixelViewerPlane plane; 
plane.width = 1024; 
plane.height = 768; 
plane.data = pixelBuffer; 
plane.rowBytes = plane.width * 4; 
[pixelViewer displayPixelBufferPlanes: &plane count: 1 withCompletion:nil]; 

Lặp lại các displayPixelBufferPlanes gọi cho mỗi khung (mà tải bộ đệm pixel để sử dụng GPU glTexImage2D), và đó là khá nhiều tất cả để có nó. Mã thông minh ở chỗ nó cố gắng sử dụng GPU cho bất kỳ loại xử lý đơn giản nào cần thiết, chẳng hạn như hoán đổi các kênh màu, chuyển đổi YpCbCr thành RGB, v.v.

Ngoài ra còn có một chút logic để tôn vinh việc chia tỷ lệ bằng cách sử dụng Thuộc tính contentMode của UIView, do đó, UIViewContentModeScaleToFit/Điền, v.v. tất cả đều hoạt động như mong đợi.

Các vấn đề liên quan