I decided to try to optimize the Android version of my li'l game, and the first thing I wanted to tackle was the slow text rendering. The easiest way seemed to be to create a bitmap via off screen rendering. That works fine and dandy - but there's an issue with uploading the texture to video memory.
The steps I perform are:
1) Create a "backbuffer", draw each individual character, and then create a gxtkSurface from it. 2) When calling the Draw method of the backbuffer, I use the normal DrawSurface in mojo.
However, the texture doesn't get uploaded to video mem before I actually do a DrawSurface call. Which means that I get a flicker - first it renders nothing for a frame or two, and then - after the texture is uploaded - it shows the texture as expected.
"Well OK," I thought. "I'll just call it directly when I create the gxtkSurface." No dice. It needs to be called in OnRender, not OnUpdate.
Alright, I thought; then I do a double-rendering for a frame or two. I draw both the backbuffer and the original text, and after that I only use the backbuffer. I'll still gain some performance in the long run. But that causes a major delay on my HTC Desire. Uploading a texture to video mem is EXTREMELY slow on my Desire... So the app freezes for a second.
In summary: does anyone know a good way to handle texture uploading? Can it be performed in a separate thread? Can it be sped up? Should I use another format than ARBG_8888? This slowness is also causing major problems for my loading class - I need to first load the textures (which is fast), and then I need to present a static screen while pre-caching everything, which takes AGES.
FYI, my experimental backbuffer code:
Import "native/backbuffer.${TARGET}.${LANG}"
Import mojo
Extern
Class Backbuffer="fontBackbuffer"
Method Create(w:Int, h:Int)
Method SetColor(r:Int, g:Int, b:Int)
Method DrawImageRect(image:Surface, startx:Int, starty:Int, x:Int, y:Int, w:Int, h:Int)
Method Finalize()
Method Draw(x:Int, y:Int)
End Class
Public
Function DrawBackbufferImageRect(b:Backbuffer, image:Image, startx:Int, starty:Int, x:Int, y:Int, w:Int, h:Int)
b.DrawImageRect(image.surface, startx, starty, x, y, w, h)
End
class fontBackbuffer{
private Bitmap backbuffer = null;
private Canvas canvas = null;
private gxtkSurface surface = null;
private Paint paint = null;
public void Create(int w, int h) {
backbuffer = Bitmap.createBitmap( w+16, h+16, Bitmap.Config.ARGB_8888 );
canvas = new Canvas( backbuffer );
}
public void SetColor(int r, int g, int b) {
int col = Color.argb( 255, r, g, b );
paint = new Paint( col );
ColorFilter filter = new PorterDuffColorFilter( col, PorterDuff.Mode.MULTIPLY );
paint.setColorFilter( filter );
}
public void DrawImageRect(gxtkSurface image, int startx, int starty, int x, int y, int w, int h) {
canvas.drawBitmap( image.bitmap, new Rect(x, y, x+w, y+h), new Rect(startx+8, starty+8, startx+w+8, starty+h+8), paint );
}
public void Finalize() {
surface = new gxtkSurface( backbuffer );
}
public void Draw(int x, int y) {
bb_graphics.bb_graphics_ValidateMatrix();
bb_graphics.bb_graphics_context.f_device.DrawSurface( surface, x - 8, y - 8 );
}
}
Note: Extra padding at the sides due to a rendering issue with AngelCode. Also, some mojo modifications are necessary, to make Surface public instead of private.
|