В общем есть такая формула (blending): Result := Fa * (Frgb - Brgb) shr 8 + Brgb, которую я перевожу на MMX. Здесь Fa - это байт, Frgb, Brgb, Result - dword. И всё бы хорошо, если бы всегда было Frgb > Brgb (побайтово, младшие 3 разряда), но в противном случае никак не могу получить правильный результат. Посмотрите, пожалуйста, и помогите найти правильное решение, а то уже голова не варит Вот код и лог выполнения на примере таких данных (случай Frgb > Brgb, правильный результат): f = EAX = B7 58 58 58 (старший разряд = Fa, остальные - Frgb) b = EDX = 53 1D 1D 54 Код (Text): MOVD MM1,EAX //* 00 00 00 00 B7 58 58 58 =Fa PXOR MM3,MM3 PUNPCKLBW MM1,MM3 //* 00 B7 00 58 00 58 00 58 =Fa: byte to word MOVD MM0,EAX //* 00 00 00 00 B7 58 58 58 =f PUNPCKHWD MM1,MM1 //* 00 B7 00 B7 00 58 00 58 MOVD MM2,EDX //* 00 00 00 00 53 1D 1D 54 =b PUNPCKHDQ MM1,MM1 //* 00 B7 00 B7 00 B7 00 B7 = выделил только Fa PSUBB MM0,MM2 //* 00 00 00 00 64 3B 3B 04 =f-b PUNPCKLBW MM0,MM3 //* 00 64 00 3B 00 3B 00 04 =f-b: byte to word PMULLW MM0,MM1 //* 47 7C 2A 2D 2A 2D 02 DC =Fa*(f-b): word PSRLW MM0,8 //* 00 47 00 2A 00 2A 00 02 =Fa*(f-b) shr 8: word PUNPCKLBW MM2,MM3 //* 00 53 00 1D 00 1D 00 54 =b: byte to word PADDW MM2,MM0 //* 00 9A 00 47 00 47 00 56 =Fa*(f-b) shr 8 + b: word PACKUSWB MM2,MM2 //* 9A 47 47 56 9A 47 47 56 = pack result MOVD EDX,MM2 //* 9A 47 47 56 Ниже случай Frgb < Brgb, неправильный результат: f = EAX = 83 00 00 00 (старший разряд = Fa, остальные - Frgb) b = EDX = 53 1D 1D 54 Код (Text): MOVD MM1,EAX //* 00 00 00 00 83 00 00 00 =Fa PXOR MM3,MM3 PUNPCKLBW MM1,MM3 //* 00 83 00 00 00 00 00 00 =Fa: byte to word MOVD MM0,EAX //* 00 00 00 00 83 00 00 00 =f PUNPCKHWD MM1,MM1 //* 00 83 00 83 00 00 00 00 MOVD MM2,EDX //* 00 00 00 00 53 1D 1D 54 =b PUNPCKHDQ MM1,MM1 //* 00 83 00 83 00 83 00 83 = выделил только Fa PSUBB MM0,MM2 //* 00 00 00 00 30 E3 E3 AC =f-b PUNPCKLBW MM0,MM3 //* 00 30 00 E3 00 E3 00 AC =f-b: byte to word PMULLW MM0,MM1 //* 18 90 74 29 74 29 58 04 =Fa*(f-b): word PSRLW MM0,8 //* 00 18 00 74 00 74 00 58 =Fa*(f-b) shr 8: word PUNPCKLBW MM2,MM3 //* 00 53 00 1D 00 1D 00 54 =b: byte to word PADDW MM2,MM0 //* 00 6B 00 91 00 91 00 AC =Fa*(f-b) shr 8 + b: word PACKUSWB MM2,MM2 //* 6B 91 91 AC 6B 91 91 AC = pack result MOVD EDX,MM2 //* 6B 91 91 AC !!! а должно быть 6C 0E 0E 29 Ошибка случается из-за того, что в строке PSUBB MM0,MM2 пропадают знаки результата операции. Как выйти из этой ситуации?
Relic Если переписать формулу так: Result := Frgb*Fa/256 + Brgb*(256-Fa)/256, то отрицательные числа исчезают.
Black_mirror Да, это выход, спасибо. Интересно, из-за такого преобразования формулы (было 4, стало 6 операций) насколько упадет, если упадет, производительность?
Мне кажется проблема в том, что вычитаются байты, а не слова. Такой код имеется для случа с единим фактором смешивания(не проверял, т.к. использую другой способ): 4. Alpha blended ================ movd mm4,eax punpcklwd mm4,mm4 psrlw mm4,8 ; alpha pxor mm7,mm7 : movd mm0,dword ptr[esi] movd mm1,dword ptr[edx] punpcklbw mm0,mm7 punpcklbw mm1,mm7 psubw mm0,mm1 psllw mm1,8 pmullw mm0,mm4 paddw mm1,mm0 psrlw mm1,8 packuswb mm1,mm1 movd dword ptr[edi],mm1 add esi,4 add edx,4 add edi,4