¿Por qué Render renderContext es más lento que dibujar en la pantalla?

Tengo un CAShapeLayer bastante grande que estoy renderizando. La capa es completamente estática, pero está contenida en un UIScrollView para que pueda moverse y ampliarse, básicamente, debe volverse a dibujar de vez en cuando. En un bash de mejorar la velocidad de fotogtwigs de este desplazamiento, establezco shouldRasterize = YES en la capa, que funcionó perfectamente. Como nunca cambio ninguna propiedad de la capa, nunca se pierde una rasterización y obtengo un sólido de 60 fps. Altos cinco por todas partes, ¿verdad?

Hasta que la capa se haga un poco más grande. Eventualmente, y no lleva mucho time, la image rasterizada es demasiado grande para que la GPU la maneje. Según mi console, <Notice>: CoreAnimation: surface 2560 x 4288 is too large y no dibuja nada en la pantalla. Realmente no lo culpo, 2560 x 4288 es bastante grande, pero pasé un rato rascándome la cabeza antes de notar esto en la console del dispositivo.

Ahora, mi pregunta es: ¿cómo puedo evitar esta limitación? ¿Cómo puedo rasterizar una capa realmente grande?

La solución obvia parece ser romper la capa en múltiples subcapas, digamos una por cada cuadrante, y rasterizar cada una de manera independiente. ¿Hay una forma fácil de hacer esto? ¿Puedo crear una nueva capa que muestre un área rectangular de otra capa? ¿O hay alguna otra solución que debería explorar?

Editar

Crear un mosaico de mosaico parece tener un performance realmente malo porque las capas se vuelven a ttwig cada vez que entran en la pantalla, creando una experiencia de desplazamiento muy irregular. ¿Hay alguna forma de almacenar en caching esas rasterizaciones? ¿O es este el enfoque equivocado por completo?

Editar

Bien, aquí está mi solución actual: renderiza la capa una vez a un CGImageRef . Cree múltiples capas de mosaico utilizando sub-rectangularjs de esa image y, de hecho, colóquelas en la pantalla.

 - (CALayer *)getTiledLayerFromLayer:(CALayer *)sourceLayer withHorizontalTiles:(int)horizontalTiles verticalTiles:(int)verticalTiles { CALayer *containerLayer = [CALayer layer]; CGFloat tileWidth = sourceLayer.bounds.size.width / horizontalTiles; CGFloat tileHeight = sourceLayer.bounds.size.height / verticalTiles; // make sure these are integral, otherwise you'll have image alignment issues! NSLog(@"tileWidth:%f height:%f", tileWidth, tileHeight); UIGraphicsBeginImageContextWithOptions(sourceLayer.bounds.size, NO, 0); CGContextRef tileContext = UIGraphicsGetCurrentContext(); [sourceLayer renderInContext:tileContext]; CGImageRef image = CGBitmapContextCreateImage(tileContext); UIGraphicsEndImageContext(); for(int horizontalIndex = 0; horizontalIndex < horizontalTiles; horizontalIndex++) { for(int verticalIndex = 0; verticalIndex < verticalTiles; verticalIndex++) { CGRect frame = CGRectMake(horizontalIndex * tileWidth, verticalIndex * tileHeight, tileWidth, tileHeight); CGRect visibleRect = CGRectMake(horizontalIndex / (CGFloat)horizontalTiles, verticalIndex / (CGFloat)verticalTiles, 1.0f / horizontalTiles, 1.0f / verticalTiles); CALayer *tile = [CALayer layer]; tile.frame = frame; tile.contents = (__bridge id)image; tile.contentsRect = visibleRect; [containerLayer addSublayer:tile]; } } CGImageRelease(image); return containerLayer; } 

Esto funciona muy bien … tipo de. Por un lado, obtengo un outlook de 60fps y el zoom de una capa de 1980 x 3330 en un iPad retina. ¡Por otro lado, tarda 20 segundos en comenzar! Entonces, mientras que esta solución resuelve mi problema original, me da una nueva: ¿cómo puedo generar las fichas más rápido?

Literalmente, todo el time se gasta en [sourceLayer renderInContext:tileContext]; llamada. Esto me parece raro, porque si solo agrego esa capa directamente, puedo hacerlo aproximadamente 40 veces por segundo, de acuerdo con el Core Animation Instrument. ¿Es posible que crear mi propio context de image provoque que no use la GPU o algo así?

Romper la capa en mosaicos es la única solución. Sin embargo, puede implementarlo de muchas maneras diferentes. Sugiero hacerlo manualmente (creando capas y subcapas por su count), pero muchos recomiendan usar CATiledLayer http://www.mlsite.net/blog/?p=1857 , que es la forma en que se implementan los maps: el zoom y la rotation son Bastante fácil con este. Las fichas de CATiledLayer se cargan (dibujan) a pedido , justo después de que se colocan en la pantalla. Esto implica un breve retraso (parpadeo) antes de que el mosaico esté dibujado por completo y AFAIK es bastante difícil deshacerse de este comportamiento.