Here are performance tests that compares blit speed of Squeak and Pygame, a game programming library for Python built on top of SDL (www.pygame.org).
Test were done on an IBM Thinkpad T40 1.2 MHz, running latest Squeak 3.9 on Windows XP, and latest version of Pygame.
The extent of the image 'Waterfall.png' is 1024@768. The extent of the image 'Jewel.png' is 140@194 (this is a sprite that has transparency).
Squeak test code follows here:
background := (Form fromFileNamed: 'Waterfall.png') asFormOfDepth: 32. sprite := (Form fromFileNamed: 'Jewel.png') asFormOfDepth: 32. buffer := Form extent: 1024@768 depth: 32.
bb := BitBlt current new. bb setDestForm: buffer sourceForm: sprite fillColor: nil combinationRule: Form over destOrigin: 0@0 sourceOrigin: 0@0 extent: sprite extent clipRect: buffer boundingBox.
t := [1000 timesRepeat: [bb copyBits]] timeToRun. Transcript show: 'Time for 1000 sprite blits Form over: ', t asString; cr.
bb combinationRule: Form paint. t := [1000 timesRepeat: [bb copyBits]] timeToRun. Transcript show: 'Time for 1000 sprite blits Form paint: ', t asString; cr.
bb combinationRule: Form blend. t := [1000 timesRepeat: [bb copyBits]] timeToRun. Transcript show: 'Time for 1000 sprite blits Form blend: ', t asString; cr.
bb := BitBlt current new. bb setDestForm: buffer sourceForm: background fillColor: nil combinationRule: Form over destOrigin: 0@0 sourceOrigin: 0@0 extent: background extent clipRect: buffer boundingBox.
t := [1000 timesRepeat: [bb copyBits]] timeToRun. Transcript show: 'Time for 1000 image blits Form over: ', t asString; cr.
rect:= 0@0 extent: 1024@768. t := [1000 timesRepeat: [ Display forceToScreen: rect]] timeToRun. Transcript show: 'Time for 1000 screen updates: ', t asString; cr.
Here goes the Python code:
import pygame from pygame.locals import *
GScreenWidth = 1024 GScreenHeight = 768
pygame.init()
screen = pygame.display.set_mode((GScreenWidth, GScreenHeight))
background = pygame.image.load("Waterfall.png") background = background.convert()
sprite = pygame.image.load("Jewel.png") sprite1 = sprite.convert() colorkey = sprite1.get_at((0,0)) sprite1.set_colorkey(colorkey, RLEACCEL) sprite2 = sprite.convert_alpha()
buf = pygame.Surface((1024, 768)) buf.convert()
startTime = pygame.time.get_ticks(); destPoint = 0,0 for i in xrange(1000): buf.blit(sprite1, destPoint) endTime = pygame.time.get_ticks(); print "Time for 1000 sprite1 blits:", endTime - startTime
startTime = pygame.time.get_ticks(); destPoint = 0,0 for i in xrange(1000): buf.blit(sprite2, destPoint) endTime = pygame.time.get_ticks(); print "Time for 1000 sprite2 blits:", endTime - startTime
startTime = pygame.time.get_ticks(); destPoint = 0,0 for i in xrange(1000): buf.blit(background, destPoint) endTime = pygame.time.get_ticks(); print "Time for 1000 image blits:", endTime - startTime
startTime = pygame.time.get_ticks(); for i in xrange(1000): pygame.display.update() endTime = pygame.time.get_ticks(); print "Time for 1000 screen updates:", endTime - startTime
pygame.quit()
Here are the results from the Squeak tests:
Time for 1000 sprite blits Form over: 250 Time for 1000 sprite blits Form paint: 775 Time for 1000 sprite blits Form blend: 1051 Time for 1000 image blits Form over: 8579 Time for 1000 screen updates: 21955
Here are the results from the Pygame tests:
Time for 1000 sprite1 blits: 50 (very fast transparent blit) Time for 1000 sprite2 blits: 373 Time for 1000 image blits: 7090 (Squeak is not that slower) Time for 1000 screen updates: 7031
I have looked a bit at the Windows VM sources and in sqWin32Window.c in function ioShowDisplay it seems that the Windows call SetDIBitsToDevice is used to put the pixels on the display. Is this a bottleneck when it comes to the display update speed? I guess SetDIBitsToDevice converts the DIB to the pixel format of the graphics card?
Best, Micke