VC驿站

?找回密码
?加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 3888|亚博体育登录失败: 6
打印 上一主题 下一主题

这一回学会多媒体指令

[复制链接]
001
75_avatar_middle
跳转到指定楼层
1#
在线会员 发表于 2019-5-26 14:57:22 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
? ???例子还是从我opengl例程中一段代码说起,在我opengl例程有这样一段代码。
? ?? ???for (int i = 0;i < h;i++) {
? ?? ?? ?? ?? ? for (int j = 0;j < w;j++) {
? ?? ?? ?? ?? ?? ?? ?? ?int pos = i*w + j;
? ?? ?? ?? ?? ?? ?? ?? ?DWORD dw = pdw[pos];
? ?? ?? ?? ?? ?? ?? ?? ?if (dw > 0) {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???if (dw & 0x00ffffff) dw |= 0xff000000;
? ?? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ?? ?? ?? ?? ?pdw[pos] = dw;
? ?? ?? ?? ?? ? }
? ?? ???}
??这段代码有两次,一次是载入的时候,另一次是渲染的时候。由于没采取每帧刷新,优化显得不是很必要,
1000ms内都能接受。这段代码作用是为opengl的alpha测试做准备。把纹理有颜色的alpha都标注为不透明,
黑色的alpha值标注为0,这样alpha测试比较函数就不显示黑色,达到透明。 它是双字操作。一般优化高不了多少,
这里是为学会多媒体,专门提出来讲一讲。
? ?为了学习,再简化一下代码,用下面这段,区别避免双循环,讲起来麻烦。
void CCAlphatest(BYTE *p, UINT len)
{
? ?? ???DWORD*pdw = (DWORD*)p;
? ?? ???len /= 4;
? ?? ???for (UINT i = 0;i < len;i++) {
? ?? ?? ?? ?? ?? ?? ?? ?DWORD dw = pdw[ i ];
??? ?? ?? ?? ?? ?? ?? ?if (dw > 0) {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???if (dw & 0x00ffffff) dw |= 0xff000000;
? ?? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ?? ?? ?? ?? ?pdw = dw;
? ?? ???}
}从反汇编开始:
[ i ] 这一回学会多媒体指令

看之前,一定要注意,不要一讲什么汇编,就一定是高效率,C编译过去都是汇编。汇编是常态,不是什么很稀奇的东西。
看了这段反汇编,这段反汇编的印象最深的是什么?
没什么印象,那就自己以后慢慢看。只用自己摸索出来,才能深深刻在记忆里。
我下面的例程就是用32,64,128位分别实现上述代码。含C代码,没剔除。
数据是临时构建地,这几个函数执行的结果是一样。在注释行已经详解了代码。
和反汇编那段是有点区别地,是在寄存器上操作。还用了两种:1掩码,2移位来实现,
主要让人明白。方法越多,越能找到自己钟爱的。
所用指令都是最常见地,现行编译器支持地,不明白就到网上搜。

#include "stdafx.h"
#include
#include
#include
#include
#include ? ?
#include
#include
using namespace std;
//不用掩码,用移位的32位数据操作
void alphatest32l(BYTE *p, int len)
{
_asm {
??;lea esi, p;
??mov esi, p;
??mov ecx, len;
cont:
??mov eax, [esi];取4字节数据
??shl eax,8;
??shr eax,8
??cmp eax, 0;检测是否存在颜色数据
??jle nextstep;
??or eax, 0ff000000h;有颜色数据置不透明
nextstep :
??mov[esi], eax;写回源位置
??add esi, 4;
??sub ecx, 4;
??cmp ecx, 0;
??jle endt;
??jmp cont;
endt:
}
}
//用掩码的32位数据操作
void alphatest32(BYTE *p,int len)
{
_asm {
??;lea esi, p;
??mov esi, p;
??mov ecx, len;
cont:
??mov eax, [esi];取4字节数据
??mov edx, 000ffffffh;
??and eax,edx;屏蔽a
??cmp eax, 0;检测是否存在颜色数据
??jle nextstep;
??not edx;
??or eax, edx;有颜色数据置不透明
nextstep:
??mov[esi], eax;写回源位置
??add esi, 4;
??sub ecx, 4;
??cmp ecx, 0;
? ?? ???jle endt;
??jmp cont;
? ? endt:
}
}

//不用掩码,用移位的64位数据操作
void alphatest64l(BYTE *p, int len)
{
_asm {
??;lea esi, p;
??mov esi, p;
??mov ecx, len;
cont:
??;取8字节数据
??movq mm0, [esi];
??;屏蔽a
??pslld mm0, 8;
??psrld mm0, 8;
??;将64位数据高32位拆到mm1
??pxor mm1, mm1;
??punpckhdq mm1, mm0;
??;移到低位,先处理高32位
??psrlq mm1, 32;
??movd eax, mm1;
??cmp eax, 0;
??jle aaaa;
??;重置a
??mov eax,0ff000000h;
??movd mm3, eax;
??psllq mm3, 32;
??por mm0, mm3
aaaa:
??;处理低32位,也可以不拆,直接传送低32位数据到寄存器
??pxor mm1, mm1;
??punpckldq mm1, mm0;
??psrlq mm1, 32;
??movd eax, mm1;
??cmp eax, 0;
??jle bbbb;
??;重置a
??mov eax, 0ff000000h;
??movd mm3, eax;
??por mm0, mm3;
bbbb:
??movq[esi], mm0;
??add esi, 8;
??sub ecx, 8;
??cmp ecx, 0;
??jle endt;
??jmp cont;
endt:
??emms;
}
}
//用掩码的64位数据操作
void alphatest64(BYTE *p, int len)
{
//abgr
unsigned __int64 mask??= 0x00ffffff00ffffff;
unsigned __int64 mask1 = 0xff00000000000000;
unsigned __int64 mask2 = 0x00000000ff000000;
_asm {
??;lea esi, p;
??mov esi, p;
??mov ecx, len;
??movq mm3, mask;
??movq mm4, mask1;
??movq mm5, mask2;
cont:
??;取8字节数据
??movq mm0, [esi];
??;屏蔽a
??pand mm0, mm3;mask
??;将64位数据高32位拆到mm1
??pxor mm1, mm1;
??punpckhdq mm1, mm0;
??;移到低位,先处理高32位
??psrlq mm1, 32;
??movd eax, mm1;
??cmp eax, 0;
??jle aaaa;
??;重置a
??por mm0, mm4;mask1
aaaa:
??;处理低32位,也可以不拆,直接传送低32位数据到寄存器
??pxor mm1, mm1;
??punpckldq mm1, mm0;
??psrlq mm1, 32;
??movd eax, mm1;
??cmp eax, 0;
??jle bbbb;
??;重置a
??por mm0, mm5;mask2
bbbb:
??movq[esi], mm0;
??add esi, 8;
??sub ecx, 8;
??cmp ecx, 0;
??jle endt;
??jmp cont;
endt:
??emms;
}
}
//不用掩码,用移位的128位数据操作
void alphatest128l(BYTE *p, int len)
{
_asm {
??;lea esi, p;
??mov esi, p;
??mov ecx, len;
cont:
??;取16字节数据
??movdqu xmm0, [esi];
??;屏蔽a
??pslld xmm0,8
??psrld xmm0,8
??;将128位拆分为两个64位数
??pxor xmm1, xmm1;
??pxor xmm2, xmm2;
??punpckhqdq xmm1, xmm0;
??punpcklqdq xmm2, xmm0;
??;将64位数移到低64位
??psrldq xmm1, 8
??psrldq xmm2, 8
??;将xmm低64位移到mmx64位寄存器
??movdq2q??mm0, xmm1;
??movdq2q??mm1, xmm2;
??;将mmx64位数拆到通用寄存器32位数
??movd edx, mm0;
??psrlq mm0, 32;
??movd eax, mm0;
??;
??;处理32位数
??;
??;第1个双字
??cmp eax, 0;
??jle aaaa;
??mov eax, 0ff000000h;
??movd xmm3, eax;
??pslldq xmm3, 12;
??por xmm0, xmm3;
aaaa :
??;第2个双字
??cmp edx, 0;
??jle bbbb;
??mov eax, 0ff000000h;
??movd xmm3, eax;
??pslldq xmm3, 8;
??por xmm0, xmm3;
bbbb :
??;将mmx64位数拆到通用寄存器32位数
??movd edx, mm1;
??psrlq mm1, 32;
??movd eax, mm1;
??;第3个双字
??cmp eax, 0;
??jle cccc;
??mov eax, 0ff000000h;
??movd xmm3, eax;
??pslldq xmm3, 4;
??por xmm0, xmm3;
cccc :
??;第4个双字
??cmp edx, 0;
??jle dddd;
??mov eax, 0ff000000h;
??movd xmm3, eax;
??;pslld xmm3, 0;
??por xmm0, xmm3;
dddd :
??movdqu[esi], xmm0;
??add esi, 16;
??sub ecx, 16;
??cmp ecx, 0;
??jle endt;
??jmp cont;
endt:
??emms;
}
}
//用掩码的128位数据操作
void alphatest128(BYTE *p, int len)
{
//注意:128位数据用字节描述,与字节的顺序是反地,最低字节为128位最高字节
//? ?? ?128位数据 - abgr? ? 字节 rgba
BYTE mask[16]??= { 0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00 };
BYTE mask1[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff };
BYTE mask2[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00 };
BYTE mask3[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
BYTE mask4[16] = { 0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
_asm {
??;lea esi, p;
??mov esi, p;
??mov ecx, len;
??movdqu xmm3, mask;
??movdqu xmm4, mask1;
??movdqu xmm5, mask2;
??movdqu xmm6, mask3;
??movdqu xmm7, mask4;
cont:
??;取16字节数据
??movdqu xmm0, [esi];
??;屏蔽a
??pand xmm0, xmm3;mask
??;将128位拆分为两个64位数
??pxor xmm1, xmm1;
??pxor xmm2, xmm2;
??punpckhqdq xmm1, xmm0;
??punpcklqdq xmm2, xmm0;
??;将64位数移到低64位
??psrldq xmm1,8
??psrldq xmm2,8
??;将xmm低64位移到mmx64位寄存器
??movdq2q??mm0, xmm1;
??movdq2q??mm1, xmm2;
??;将mmx64位数拆到通用寄存器32位数
??movd edx, mm0;
??psrlq mm0, 32;
??movd eax, mm0;
??;
??;处理32位数
??;
??;第1个双字
??cmp eax, 0;
??jle aaaa;
??por xmm0, xmm4;mask1
aaaa:
??;第2个双字
??cmp edx, 0;
??jle bbbb;
??por xmm0, xmm5;mask2
bbbb:
??;将mmx64位数拆到通用寄存器32位数
??movd edx, mm1;
??psrlq mm1, 32;
??movd eax, mm1;
??;第3个双字
??cmp eax, 0;
??jle cccc;
??por xmm0, xmm6;mask3
cccc:
??;第4个双字
??cmp edx, 0;
??jle dddd;
??por xmm0, xmm7;mask4
dddd:
??movdqu[esi], xmm0;
??add esi, 16;
??sub ecx, 16;
??cmp ecx, 0;
??jle endt;
??jmp cont;
endt:
??emms;
}
}
void CAlphatest(BYTE *p, int len)
{
DWORD*pdw = (DWORD*)p;
int h = 3;
int w = 4;
for (int i = 0;i < h;i++) {
??for (int j = 0;j < w;j++) {
? ?int pos = i*w + j;
? ?DWORD dw = pdw[pos];
? ?if (dw > 0) {
? ? if (dw & 0x00ffffff) dw |= 0xff000000;
? ?}
? ?pdw[pos] = dw;
??}
}
}
void CCAlphatest(BYTE *p, UINT len)
{
DWORD*pdw = (DWORD*)p;
len /= 4;
for (UINT i = 0;i < len;i++) {
? ?DWORD dw = pdw[ i ];
? ?if (dw > 0) {
? ? if (dw & 0x00ffffff) dw |= 0xff000000;
? ?}
? ?pdw[ i ] = dw;
}
}

int main()
{
DWORD data[] = {
??RGB(255,0,0),
??RGB(255,255,0),
??RGB(255,255,255),
??RGB(0,0,0),
??RGB(0,255,0),
??RGB(0,255,255),
??RGB(255,255,0),
??RGB(0,0,0),
??RGB(128,128,0),
??RGB(255,0,0),
??RGB(0,0,128),
??RGB(0,0,128),
};
//之前数据
int len = (sizeof data / sizeof data[0]);
cout << "before data:" << endl;
for (int i = 0;i < len;i++)
{
??cout <<"0x" << setw(8)<< setfill('0') << hex <
??if (i % 2 == 1) cout << endl;
}
cout << endl;
int datalen = len * sizeof(DWORD);
//这些函数需要取消注释一个一个测试,因为数据是共享地,否则就看不到效果
//alphatest32((BYTE*)data,datalen);
//alphatest64((BYTE*)data, datalen);
//alphatest128((BYTE*)data, datalen);
//CAlphatest((BYTE*)data, datalen);
//alphatest32l((BYTE*)data,datalen);
//alphatest64l((BYTE*)data, datalen);
alphatest128l((BYTE*)data, datalen);
//之后数据
cout << "after data:" << endl;

for (int i = 0;i < len;i++)
{
??cout << "0x" << setw(8) << setfill('0') << hex << data[ i ] << dec << " ";
??if (i % 2 == 1) cout << endl;
}
cout << endl;
system("pause");
return 0;
}

这一回学会多媒体指令??不知道看懂的有多少,看不懂就保存吧,等懂的时候再看。
? ?? ?? ?? ???通过它绝对能学会,但是学不学的会,不是我说了算。



评分

参与人数 1驿站币 +2 热心值 +2 收起 理由
58_avatar_small 敏敏 + 2 + 2 很给力!

查看全部评分





上一篇:大家来找茬挂
下一篇:推箱子
58_avatar_middle
2#
online_vip 发表于 2019-5-27 16:49:24 | 只看该作者
我有信心,如果一行代码,一行代码分析一定能学会,只是目前在搞别的方法。收藏,楼主出品,必为精华!
51_avatar_middle
3#
online_admins 发表于 2019-5-28 01:38:46 | 只看该作者
网友们还真是不识货啊,这么好的文章还不亚博体育登录失败拜读!顶起
61_avatar_middle
4#
donate_vip 发表于 2019-5-28 09:09:00 | 只看该作者
这是嘛呀?,咱也不知道,咱也不敢问那!这一回学会多媒体指令
36_avatar_middle
5#
在线会员 发表于 2019-6-8 08:29:57 | 只看该作者
本帖最后由 王者归来339 于 2019-6-8 08:59 编辑

加精华,应该是好贴了
84_avatar_middle
6#
在线会员 发表于 2019-7-23 07:10:24 | 只看该作者
先mark了,暂时没时间研究
59_avatar_middle
7#
在线会员 发表于 4?天前 | 只看该作者
过来顶顶贴,不过最后一句话真的在理这一回学会多媒体指令
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )?tongdun|网站地图wx_jqr

GMT+8, 2019-8-16 10:01

Powered by Discuz! X3.4

? 2009-2019 cctry.com

快速亚博体育登录失败 返回顶部 返回列表