Blit Optimization

10 views
Skip to first unread message

Gerdus van Zyl

unread,
May 29, 2007, 4:01:00 PM5/29/07
to pyglet-users
How can I reduce the time to blit to a texture?
The size is 446x285 but takes 0.88 to 1.7 seconds to blit to texture.
I am using the method used in the media player sample.

The code I use, and is called in the program loop. The source
(surf_clip) is a cairo image surface.

s = str(surf_clip.get_data())
pitch = sw * len('BGRA') * -1
imagedata = image.ImageData(sw, sh, 'BGRA', s,pitch )

texture = self.texture
glBindTexture(texture.target, texture.id)

#rx and ry = 0, will be used to update only part that changed

imagedata.blit_to_texture(texture.target, 0, rx, ry, 0)

And the self.texture exactly like media/video:

def _get_texture(self):
if not self._texture:
glEnable(GL_TEXTURE_2D)
texture = image.Texture.create_for_size(GL_TEXTURE_2D,
self.width, self.height, GL_RGB)
if texture.width != self.width or texture.height !=
self.height:
self._texture = texture.get_region(
0, 0, self.width, self.height)
else:
self._texture = texture
return self._texture
texture = property(_get_texture)

Alex Holkner

unread,
May 29, 2007, 6:17:23 PM5/29/07
to pyglet...@googlegroups.com
ImageData does some magic behind the scenes to mash data into a format
that GL will accept. This is really handy for the image decoders, but
can lead to performance problems which are avoidable for this kind of thing.

The most obvious problem is using a negative pitch (top-to-bottom image
rows) -- GL has no way of accepting this data, so ImageData splits the
data and reorders it first. Use a positive pitch (or better, leave
pitch as the default, which is tightly packed) and swap the texture
coordinates instead (to render it "upside-down").

The other problem is the image format. We're lacking documentation on
which formats are supported by GL and which are mashed by ImageData, but
you can see what happens in pyglet/image/__init__.py, in
ImageData._get_gl_format_and_type() (line 798 atm). BGRA is not
supported on any platform (and so will be mashed -- slowly -- by
ImageData), so see if you can get Cairo to use a different surface
format. RGB or RGBA is supported everywhere, and BGR, ABGR or ARGB are
supported if certain GL extensions are present.

Good luck
Alex.

Gerdus van Zyl

unread,
May 30, 2007, 10:34:51 AM5/30/07
to pyglet-users
Thanks that helped alot.

For future reference here is my solution:

negative pitch is countered by flipping the texture coordinates as
suggested:
#default: texture.tex_coords = ((0, 0, 0), (1, 0, 0), (1, 1, 0), (0,
1, 0))
texture.tex_coords = ((0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 0))

The image format was solved by converting it beforehand using numpy:
#BGRA TO RGB

a = numpy.frombuffer(surf_clip.get_data(), numpy.uint8)
a.shape = (sw, sh, 4)
a = a[:,:,0:3] #drop alpha channel
temp = copy(a[:,:,0])

a[:,:,0] = a[:,:,2]
a[:,:,2] = temp

After all that blit time was reduced to 0.0014 seconds a 7x
improvement :-)
My next optimization step is to use glitz, but first i have to make
python bindings...

Alex Holkner

unread,
May 30, 2007, 10:44:25 AM5/30/07
to pyglet...@googlegroups.com
Gerdus van Zyl wrote:
> Thanks that helped alot.
>
> For future reference here is my solution:
>
> negative pitch is countered by flipping the texture coordinates as
> suggested:
> #default: texture.tex_coords = ((0, 0, 0), (1, 0, 0), (1, 1, 0), (0,
> 1, 0))
> texture.tex_coords = ((0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 0))
>
> The image format was solved by converting it beforehand using numpy:
> #BGRA TO RGB
>
Something that occurred to me after posting this morning (and talking to
Richard).. you can use the GL color matrix (present with the ARB_imaging
extension, which is pretty universal) to do the conversion. I've added
it to my todo list to improve ImageData's performance in the future.

Alex.

Alex Holkner

unread,
Jun 8, 2007, 9:39:29 PM6/8/07
to pyglet...@googlegroups.com
This is in r877 now: you should be able to use the original image format
without converting via numpy, without any performance loss. My test
cases are in tests/image/MATRIX_RGB and tests/image/MATRIX_RGBA.
(This doesn't address the image flipping though, you'll still need to
flip texture coordinates).

Alex.

Gerdus van Zyl

unread,
Jun 12, 2007, 7:01:13 AM6/12/07
to pyglet-users
I added the following to _get_gl_format_and_type in ImageData since
the format I am interested in is BGRA. It seems to work, don't quite
know why.

elif (format == 'BGRA' and
gl_info.have_extension('GL_EXT_bgra')):
return GL_BGRA, GL_UNSIGNED_BYTE

The colour matrix optimization was not utilized since my ATI 9500 does
not support GL_ARB_imaging according to
gl_info.have_extension('GL_ARB_imaging') [verified with glview] and
according to some googling it is not common.

Thanks for all your help :-)
Gerdus.

Alex Holkner

unread,
Jun 12, 2007, 10:24:24 AM6/12/07
to pyglet...@googlegroups.com
Thanks, was shortsighted to leave that one out :-). Is in trunk as of r897.

Alex.

Reply all
Reply to author
Forward
0 new messages