2010-03-07 13 views
10

Ben PC'den iPhone'a taşıyan bir "yazılım renderer" var. Ekranı el ile iPhone'da bir piksel tampon ile güncellemenin en hızlı yolu nedir? örneğin pencerelerde en hızlı bulduğum işlev SetDIBitsToDevice'dir.En hızlı yolu iphone üzerinde bir ekran tampon çizmek için

ben iphone veya kütüphaneler hakkında fazla bilgi sahibi ve pek çok katmanları ve kullanıcı arayüzü öğeleri farklı türleri var gibi görünmektedir, bu yüzden çok açıklama yapılması gerekebilir yok ...

şimdilik Sadece opengl'deki bir dokuyu sürekli güncelleyeceğim ve bunu ekrana sunacağım, bunun bunun en iyi yolu olacağından şüphe duyuyorum.

GÜNCELLEME: Ben openGL ekran büyüklüğünde doku yöntemi denedi

:

Ben 17fps var ... Bir 512x512 doku kullanılan

(o ikisinin bir güç gerektiğinden)

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

sadece çağrı hemen hemen yeniden gibiydi TÜM yavaş için desteklenebilir.

dışarı yorum, ve tüm yazılım render GUI kodunda bırakarak ve şimdi olmayan güncelleme doku oluşturma, 60fps% 30 oluşturucusu kullanımı ve cpu hiçbir kayda değer sivri sonuçlandı.

GetBuffer() yalnızca GUI sisteminin yazılım destekleyicisine bir işaretçi döndürdüğünü, arabelleğin yeniden boyutlandırılması veya yeniden boyutlandırılması olmadığını, doku için uygun şekilde boyutlandırıldığını ve biçimlendirildiğini unutmayın; yavaşlamanın yazılım işleyicisiyle ilgisi olmadığını, ki bu iyi bir haber, ekran 60'ı güncellemek için bir yol bulabilirsem, yazılımın oluşturulması şu an için çalışmalı.

512,312 yerine 512,320 numaralı güncelleştirme doku çağrısını yapmayı denedim, bu garip bir şekilde daha yavaş ... 10fps hızında çalışıyor, ayrıca render kullanımının yalnızca% 5 gibi olduğunu ve her zaman bir aramada harcanıyor diyor openGiddle32bpp'e openGLES içinde.

Yazılımımın oluşturulmasını, daha doğrudan bir harmanla sonuçlanacak olursa, herhangi bir pixle biçimine dönüştürecek şekilde değiştirebilirim.

, Bilginize (steroid böylece bir Iphone 3G gibi) bir 2.2.1 ipod touch G2

GÜNCELLEME 2 üzerinde test: Sadece CoreAnimation/Grafik yöntemi yazma bitirdikten

, iyi görünüyor, ama ben biraz eski CGImage, tamamen yeni bir tane oluşturma, her bir çerçeve ekran güncelleme hakkında endişeli biraz ... aşağıdaki 'someRandomFunction' içinde kontrol: bu görüntüyü güncellemek için en hızlı yoldur? herhangi bir yardım büyük takdir edilecektir.

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

Hey, ben de bu problemin içine koştum, her çerçeveyi oluşturmak ve yok etmek için tek çözümdür? (bunu denedim ve glTexsubimage'den daha yavaş). Doğrudan sağlayıcının tüm noktasının bu arabelleğe işaret etmesi gerektiği görünüyor, eğer değiştirirsem, görüntü güncellenir. Bunun hakkında herhangi bir yardım? –

+0

CGDataProviderCreateDirect'i kullanma noktasının CADisplayLink kullanarak yenilenen bir piksel arabelleğe doğrudan erişim olduğunu düşündüm. Ne yazık ki, bu korkunç derecede yavaş. Herhangi bir geçici çözüm bulundu? – aoakenfo

cevap

11

CGDataProviderCreateDirect kullanarak bir tampon tarafından desteklenen bir CGImage oluşturmak ve CALayer 'ın contents özelliğine o atamaktır.

En iyi sonucu elde etmek için kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little veya kCGImageAlphaNone | kCGBitmapByteOrder32Little bitmap türlerini ve çift arabelleği kullanın; böylece ekran hiçbir zaman tutarsız durumda olmaz.

düzenleme: Bu, teoride bir OpenGL dokusuna çizim yapmaktan daha hızlı olmalı, ancak her zaman olduğu gibi, emin olmak için profil.

edit2: CADisplayLink kullandığınız kompozisyon yöntemi ne olursa olsun yararlı bir sınıftır.

+0

Bu 24 fps video yapmak için yeterince hızlı olur mu? –

+0

@ St3fan: En azından 60 fps yapmak için yeterince hızlı olmasını umuyoruz! iPhone'un Api's'inin ve İşletim Sisteminin masaüstü Windows'dan daha da şişkin olduğu hissine kapılmaya başladım! @rpetrich, teşekkürler, deneyeceğim. Ben iphone dev, GUI şeyler gibi pek bir şey bilmiyorum, bu yüzden bir süre alabilir, başlamak için kullanmak için iyi bir şablon tavsiye edebilir misiniz? Sadece açık GL'yi kullandım. – matt

+0

Matt iPhone API'ları, Win32 ile karşılaştırıldığında son derece güzel. Bazı şeyler daha yüksek seviyede Kakao koduyla mümkün değildir. Bunun daha iyi bir Kakao API'sine ihtiyacı olduğunu düşünüyorsanız, Apple ile bir hata düzeltmesi yapın. –

3

en hızlı şekilde özel çerçeveler vardır IOFrameBuffer/IOSurface, kullanmaktır.

Bu yüzden OpenGL, AppStore uygulamaları için mümkün olan tek yol gibi görünüyor.En hızlı App Store yalnızca CPU 2D grafik yapmanın yolu onaylı

+0

Soruyu opengl yöntemiyle güncelledim, iyi görünmüyor. – matt

1

Belki de yazılım oluşturucusunda kullanılan yöntemleri bir GPU gölgelendiricisine aktarabilirsiniz ... daha iyi bir performans elde edebilirsiniz. Kodlanmış "video" verilerini doku olarak göndermeniz gerekir.

+0

Bu iyi bir fikir, maalesef durumum için değil, kesinlikle başkaları için. – matt

0

CGDataProvider ve glTexSubImage'dan daha hızlı bir yöntem CVOpenGLESTextureCache kullanmaktır. CVOpenGLESTextureCache, yeniden açılmadan grafik belleğindeki bir OpenGL dokusunu doğrudan değiştirmenize izin verir.

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

Kullanımı biraz zor olduğunu ve bu konuyla ilgili kendi soru sormak sonra karşıya geldi: How to directly update pixels - with CGImage and direct CGDataProvider

Burada görebileceğiniz hızlı animasyon görüntüsü için kullandı

1

Cevabımı bir cevap şeklinde @ rpetrich'in cevabına göndermek için, testlerimde OpenGL'yi en hızlı şekilde buldum. Ben EEPixelViewer denilen basit bir nesne (UIView alt sınıf) uyguladı, bu genel olarak bence çoğu insan için çalışması gerektiğini yapar.

Ekrana çok çeşitli biçimlerde (24bpp RGB, 32 bit RGBA ve birkaç YpCbCr biçimi) pikselleri olabildiğince verimli bir şekilde itmek için OpenGL kullanır. Çözüm, daha eski olanlar da dahil olmak üzere hemen her tek iOS cihazında çoğu piksel formatı için 60 fps'ye ulaşıyor. Kullanımı son derece basittir ve hiçbir OpenGL bilgi gerektirir: displayPixelBufferPlanes (glTexImage2D kullanarak GPU'ya piksel tampon yükler) her kare için çağrı

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

tekrarlayın ve bu ona orada hemen hemen hepsi bu. Kod, renk kanallarına izin vermek, YpCbCr'yi RGB vb. Gibi dönüştürmek için gerekli her türlü basit işlem için GPU'yu kullanmaya çalışacak şekilde akıllıdır.

Ayrıca, ölçeklendirmeyi onurlandırmak için biraz mantık da vardır. UIView'in contentMode özelliği, yani UIViewContentModeScaleToFit/Fill, vb. Tüm beklendiği gibi çalışır.

İlgili konular