Speed boost DrawPixmap
BlitzMax Forums/BlitzMax Module Tweaks/Speed boost DrawPixmap
| ||
Hey everyone, I have created a way to get a good 200% speed increase in DrawPixmap under opengl. If you take a look at its current implementation: Method DrawPixmap( p:TPixmap,x,y ) Local blend=state_blend DisableTex SetBlend SOLIDBLEND Local t:TPixmap=YFlipPixmap(p) If t.format<>PF_RGBA8888 t=ConvertPixmap( t,PF_RGBA8888 ) glRasterPos2i 0,0 glBitmap 0,0,0,0,x,-y-t.height,Null glDrawPixels t.width,t.height,GL_RGBA,GL_UNSIGNED_BYTE,t.pixels SetBlend blend End Method You can see two important things going on: - It will always YFLIP any pixmap you draw -> this will also create a duplicate pixmap in memory, copy your pixmap while yflipping it. - It might also convert if your pixmap was not in PF_RGBA. This would mean another full size duplicate pixmap. I have created a new method that I called: FastDrawPixmap that also supports scaling your pixmap in realtime (instead of having to use resizepixmap). Here's the code: Method FastDrawPixmap( p:TPixmap,x,y,scalex#, scaley# ) Local blend=state_blend DisableTex SetBlend SOLIDBLEND Local t:TPixmap=p If t.format<>PF_RGBA8888 t=ConvertPixmap(p, PF_RGBA8888 ) glpixelzoom scalex#,-scaley# glRasterPos2i 0,0 glBitmap 0,0,0,0,x,-y,Null glPixelStorei GL_UNPACK_ROW_LENGTH, p.pitch Shr 2 glDrawPixels p.width, p.height, GL_RGBA, GL_UNSIGNED_BYTE, p.pixels SetBlend blend End Method I removed the YFlip call by making glPixelStore supports pitch. Also with glPixelZoom with a negative y scale, the image will be drawn correctly. Scaling is supported and is super fast. Note that I didn't remove the ConvertPixmap call, so whenever possible, keep your pixmaps in PF_RGBA format so they won't get converted every frame. Here's some speed info from my iBook: Time to draw 50 times a 512x384 pixmap using DrawPixmap: 505 msec Same thing but if pixmap wasn't in PF_RGBA format: 778 msec Now the same pixmap drawn with FastDrawPixmap: 269 msec Another important speed tip: If you draw a pixmap bigger than the screen, you should always use a PixmapWindow: you'll get a major speed boost without requiring additionnal memory. |
| ||
BRL? Whould this be included in the official build? |
| ||
Many thanks for the tip! I implent this on the Mac version of my game! |
| ||
You don't really have to do a ConvertPixmap at all, OpenGL is quite capable of reading different input formats. Instead of GL_RGBA, just select the appropriate format to pass to it based on the current pixel format of the pixmap, eg... Select t.Format Case PF_RGBA8888 ReadFormat=GL_RBGA Case PF_RGB888 ReadFormat=GL_RGB8 Case PF_A8 ReadFormat=GL_Alpha etc... if you look at the code that converts a pixmap into an Image, you will find the conversion you need to transfer any format pixmap to the graphics card. That should cut out the convert altogether. What is that glBitmap() doing in there? |
| ||
It might be worth giving it a try! Saving this extra byte per pixel could be great. I'll try it later on. Thanks for the tip! glBitmap, for some obscure reason I haven't deeply investigated, makes glDrawPixels clip correctly. If you remove it, the image will not get drawn at all if any part of it goes outside the viewport. Very strange. |
| ||
Very interesting. |
| ||
AngelDaniel, I tried with PF_RGB888 -> GL_RGB, and it gave an additionnal 17% speed increase! Along with saving the cost of the pixmap conversion. Thanks for the tip! |