快速rgb565到YUV(甚至rgb565到Y)

时间:2010-01-13 11:59:12

标签: optimization assembly x86 yuv blit

我正在处理一个我希望输出选项转到视频叠加层的事情。一些支持rgb565,如果这么甜,只需复制数据。

如果不是,我必须通过转换复制数据,并且它一次是帧缓冲区。我将尝试一些事情,但我认为这可能是优化者热衷于进行一些挑战的事情之一。

通常支持的各种YUV格式最简单的是Y的平面,其后是交错的或单独的UV平面。

使用Linux / xv,但在我处理它的级别只是字节和x86。

我将以质量为代价专注于速度,但可能有数百种不同的路径可供尝试。那里有一个平衡点。

我看了mmx,但我不确定那里有什么有用的东西。没有任何东西能让我觉得特别适合这项任务,而且要把东西放到寄存器的正确位置是很多的改变。

尝试使用Y = Green * 0.5 + R * 0.25 + Blue *的原始版本。 U和V甚至不是质量明智的问题。你可以通过这些渠道谋杀。

对于一个简单的循环。

loop:
movzx eax,[esi]
add esi,2
shr eax,3
shr al,1
add ah,ah
add al,ah
mov [edi],al
add edi,1
dec count
jnz loop

当然每条指令都依赖于之前的指令而且字读取不是最好的,所以交错两个可能会获得一点

loop: 
mov eax,[esi]
add esi,4
mov ebx,eax
shr eax,3
shr ebx,19
add ah,ah
add bh,bh
add al,ah
add bl,bh
mov ah,bl
mov [edi],ax
add edi,2
dec count
jnz loop

这样做很容易,一次只有4个,也许是为了一个好处。

任何人都能更快,更好地拿出任何东西吗?

有趣的一点是,一个体面的编译器是否可以产生类似的代码。

2 个答案:

答案 0 :(得分:1)

我认为你真正想要看的是使用MMX或整数SSE指令。这样您就可以一次使用几个像素。我想如果你指定了正确的开关,你的编译器将能够生成这样的代码,特别是如果你的代码编写得足够好。

关于您现有的代码,我不打算使用不同迭代的交错指令来获得性能。所有x86处理器(不包括Atom)和缓存的无序引擎应该能很好地处理。

修改:如果您需要执行水平添加,则可能需要使用PHADDDPHADDW说明。事实上,如果您拥有英特尔软件设计手册,则应查找PH*指令。他们可能拥有你所需要的东西。

答案 1 :(得分:1)

一个不错的编译器,给定适当的开关来调整最感兴趣的CPU变体,几乎肯定比任何凡人更了解更好的x86指令选择和调度!

看看Intel(R) 64 and IA-32 Architectures Optimization Reference Manual ...

如果你想进入手工优化代码,一个好的策略可能是让编译器为你生成汇编源作为起点,然后调整它;每次更改前后的个人资料,以确保您实际上做得更好。