pngvcrd.c
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:144k
- shr al, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, bpp
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davgrlp
- // get # of bytes to alignment
- mov diff, edi // take start of row
- add diff, ebx // add bpp
- add diff, 0xf // add 7 + 8 to incr past alignment boundary
- and diff, 0xfffffff8 // mask to alignment boundary
- sub diff, edi // subtract from start ==> value ebx at alignment
- jz davggo
- // fix alignment
- // Compute the Raw value for the bytes upto the alignment boundary
- // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
- xor ecx, ecx
- davglp1:
- xor eax, eax
- mov cl, [esi + ebx] // load cl with Prior(x)
- mov al, [edx + ebx] // load al with Raw(x-bpp)
- add ax, cx
- inc ebx
- shr ax, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, diff // Check if at alignment boundary
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davglp1 // Repeat until at alignment boundary
- davggo:
- mov eax, FullLength
- mov ecx, eax
- sub eax, ebx // subtract alignment fix
- and eax, 0x00000007 // calc bytes over mult of 8
- sub ecx, eax // drop over bytes from original length
- mov MMXLength, ecx
- } // end _asm block
- // Now do the math for the rest of the row
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000000000ffffff;
- ShiftBpp.use = 24; // == 3 * 8
- ShiftRem.use = 40; // == 64 - 24
- _asm {
- // Re-init address pointers and offset
- movq mm7, ActiveMask
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- movq mm5, LBCarryMask
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov esi, prev_row // esi ==> Prior(x)
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (we correct position in loop below)
- davg3lp:
- movq mm0, [edi + ebx] // Load mm0 with Avg(x)
- // Add (Prev_row/2) to Average
- movq mm3, mm5
- psrlq mm2, ShiftRem // Correct position Raw(x-bpp) data
- movq mm1, [esi + ebx] // Load mm1 with Prior(x)
- movq mm6, mm7
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 3-5
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover the last two
- // bytes
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- // Data only needs to be shifted once here to
- // get the correct x-bpp offset.
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- add ebx, 8
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Now ready to write back to memory
- movq [edi + ebx - 8], mm0
- // Move updated Raw(x) to use as Raw(x-bpp) for next loop
- cmp ebx, MMXLength
- movq mm2, mm0 // mov updated Raw(x) to mm2
- jb davg3lp
- } // end _asm block
- }
- break;
- case 6:
- case 4:
- case 7:
- case 5:
- {
- ActiveMask.use = 0xffffffffffffffff; // use shift below to clear
- // appropriate inactive bytes
- ShiftBpp.use = bpp << 3;
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm {
- movq mm4, HBClearMask
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- // Load ActiveMask and clear all bytes except for 1st active group
- movq mm7, ActiveMask
- mov edi, row // edi ==> Avg(x)
- psrlq mm7, ShiftRem
- mov esi, prev_row // esi ==> Prior(x)
- movq mm6, mm7
- movq mm5, LBCarryMask
- psllq mm6, ShiftBpp // Create mask for 2nd active group
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (we correct position in loop below)
- davg4lp:
- movq mm0, [edi + ebx]
- psrlq mm2, ShiftRem // shift data to position correctly
- movq mm1, [esi + ebx]
- // Add (Prev_row/2) to Average
- movq mm3, mm5
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm7 // Leave only Active Group 1 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- add ebx, 8
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active
- // byte
- cmp ebx, MMXLength
- // Now ready to write back to memory
- movq [edi + ebx - 8], mm0
- // Prep Raw(x-bpp) for next loop
- movq mm2, mm0 // mov updated Raws to mm2
- jb davg4lp
- } // end _asm block
- }
- break;
- case 2:
- {
- ActiveMask.use = 0x000000000000ffff;
- ShiftBpp.use = 16; // == 2 * 8 [BUGFIX]
- ShiftRem.use = 48; // == 64 - 16 [BUGFIX]
- _asm {
- // Load ActiveMask
- movq mm7, ActiveMask
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- movq mm5, LBCarryMask
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov esi, prev_row // esi ==> Prior(x)
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (we correct position in loop below)
- davg2lp:
- movq mm0, [edi + ebx]
- psrlq mm2, ShiftRem // shift data to position correctly [BUGFIX]
- movq mm1, [esi + ebx]
- // Add (Prev_row/2) to Average
- movq mm3, mm5
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- movq mm6, mm7
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- // Data only needs to be shifted once here to
- // get the correct x-bpp offset.
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
- psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 6 & 7
- movq mm2, mm0 // mov updated Raws to mm2
- psllq mm2, ShiftBpp // shift data to position correctly
- // Data only needs to be shifted once here to
- // get the correct x-bpp offset.
- add ebx, 8
- movq mm1, mm3 // now use mm1 for getting LBCarrys
- pand mm1, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1 (Only valid for active group)
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte
- pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg
- paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
- cmp ebx, MMXLength
- // Now ready to write back to memory
- movq [edi + ebx - 8], mm0
- // Prep Raw(x-bpp) for next loop
- movq mm2, mm0 // mov updated Raws to mm2
- jb davg2lp
- } // end _asm block
- }
- break;
- case 1: // bpp == 1
- {
- _asm {
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- mov edi, row // edi ==> Avg(x)
- cmp ebx, FullLength // Test if offset at end of array
- jnb davg1end
- // Do Paeth decode for remaining bytes
- mov esi, prev_row // esi ==> Prior(x)
- mov edx, edi
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // edx ==> Raw(x-bpp)
- davg1lp:
- // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
- xor eax, eax
- mov cl, [esi + ebx] // load cl with Prior(x)
- mov al, [edx + ebx] // load al with Raw(x-bpp)
- add ax, cx
- inc ebx
- shr ax, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, FullLength // Check if at end of array
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davg1lp
- davg1end:
- } // end _asm block
- }
- return;
- case 8: // bpp == 8
- {
- _asm {
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- movq mm5, LBCarryMask
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov esi, prev_row // esi ==> Prior(x)
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes
- // (NO NEED to correct position in loop below)
- davg8lp:
- movq mm0, [edi + ebx]
- movq mm3, mm5
- movq mm1, [esi + ebx]
- add ebx, 8
- pand mm3, mm1 // get lsb for each prev_row byte
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm3, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm3 // add LBCarrys to Avg for each byte
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- paddb mm0, mm2 // add (Raw/2) to Avg for each byte
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm0
- movq mm2, mm0 // reuse as Raw(x-bpp)
- jb davg8lp
- } // end _asm block
- }
- break;
- default: // bpp greater than 8
- {
- _asm {
- movq mm5, LBCarryMask
- // Re-init address pointers and offset
- mov ebx, diff // ebx ==> x = offset to alignment boundary
- mov edi, row // edi ==> Avg(x)
- movq mm4, HBClearMask
- mov edx, edi
- mov esi, prev_row // esi ==> Prior(x)
- sub edx, bpp // edx ==> Raw(x-bpp)
- davgAlp:
- movq mm0, [edi + ebx]
- movq mm3, mm5
- movq mm1, [esi + ebx]
- pand mm3, mm1 // get lsb for each prev_row byte
- movq mm2, [edx + ebx]
- psrlq mm1, 1 // divide prev_row bytes by 2
- pand mm3, mm2 // get LBCarrys for each byte where both
- // lsb's were == 1
- psrlq mm2, 1 // divide raw bytes by 2
- pand mm1, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm3 // add LBCarrys to Avg for each byte
- pand mm2, mm4 // clear invalid bit 7 of each byte
- paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte
- add ebx, 8
- paddb mm0, mm2 // add (Raw/2) to Avg for each byte
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm0
- jb davgAlp
- } // end _asm block
- }
- break;
- } // end switch ( bpp )
- _asm {
- // MMX acceleration complete now do clean-up
- // Check if any remaining bytes left to decode
- mov ebx, MMXLength // ebx ==> x = offset bytes remaining after MMX
- mov edi, row // edi ==> Avg(x)
- cmp ebx, FullLength // Test if offset at end of array
- jnb davgend
- // Do Paeth decode for remaining bytes
- mov esi, prev_row // esi ==> Prior(x)
- mov edx, edi
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // edx ==> Raw(x-bpp)
- davglp2:
- // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
- xor eax, eax
- mov cl, [esi + ebx] // load cl with Prior(x)
- mov al, [edx + ebx] // load al with Raw(x-bpp)
- add ax, cx
- inc ebx
- shr ax, 1 // divide by 2
- add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx
- cmp ebx, FullLength // Check if at end of array
- mov [edi+ebx-1], al // Write back Raw(x);
- // mov does not affect flags; -1 to offset inc ebx
- jb davglp2
- davgend:
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized code for PNG Paeth filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
- png_bytep prev_row)
- {
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- //png_uint_32 len;
- int bpp;
- int diff;
- //int ptemp;
- int patemp, pbtemp, pctemp;
- bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
- FullLength = row_info->rowbytes; // # of bytes to filter
- _asm
- {
- xor ebx, ebx // ebx ==> x offset
- mov edi, row
- xor edx, edx // edx ==> x-bpp offset
- mov esi, prev_row
- xor eax, eax
- // Compute the Raw value for the first bpp bytes
- // Note: the formula works out to be always
- // Paeth(x) = Raw(x) + Prior(x) where x < bpp
- dpthrlp:
- mov al, [edi + ebx]
- add al, [esi + ebx]
- inc ebx
- cmp ebx, bpp
- mov [edi + ebx - 1], al
- jb dpthrlp
- // get # of bytes to alignment
- mov diff, edi // take start of row
- add diff, ebx // add bpp
- xor ecx, ecx
- add diff, 0xf // add 7 + 8 to incr past alignment boundary
- and diff, 0xfffffff8 // mask to alignment boundary
- sub diff, edi // subtract from start ==> value ebx at alignment
- jz dpthgo
- // fix alignment
- dpthlp1:
- xor eax, eax
- // pav = p - a = (a + b - c) - a = b - c
- mov al, [esi + ebx] // load Prior(x) into al
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- sub eax, ecx // subtract Prior(x-bpp)
- mov patemp, eax // Save pav for later use
- xor eax, eax
- // pbv = p - b = (a + b - c) - b = a - c
- mov al, [edi + edx] // load Raw(x-bpp) into al
- sub eax, ecx // subtract Prior(x-bpp)
- mov ecx, eax
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- add eax, patemp // pcv = pav + pbv
- // pc = abs(pcv)
- test eax, 0x80000000
- jz dpthpca
- neg eax // reverse sign of neg values
- dpthpca:
- mov pctemp, eax // save pc for later use
- // pb = abs(pbv)
- test ecx, 0x80000000
- jz dpthpba
- neg ecx // reverse sign of neg values
- dpthpba:
- mov pbtemp, ecx // save pb for later use
- // pa = abs(pav)
- mov eax, patemp
- test eax, 0x80000000
- jz dpthpaa
- neg eax // reverse sign of neg values
- dpthpaa:
- mov patemp, eax // save pa for later use
- // test if pa <= pb
- cmp eax, ecx
- jna dpthabb
- // pa > pb; now test if pb <= pc
- cmp ecx, pctemp
- jna dpthbbc
- // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth
- dpthbbc:
- // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
- mov cl, [esi + ebx] // load Prior(x) into cl
- jmp dpthpaeth
- dpthabb:
- // pa <= pb; now test if pa <= pc
- cmp eax, pctemp
- jna dpthabc
- // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth
- dpthabc:
- // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
- mov cl, [edi + edx] // load Raw(x-bpp) into cl
- dpthpaeth:
- inc ebx
- inc edx
- // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
- add [edi + ebx - 1], cl
- cmp ebx, diff
- jb dpthlp1
- dpthgo:
- mov ecx, FullLength
- mov eax, ecx
- sub eax, ebx // subtract alignment fix
- and eax, 0x00000007 // calc bytes over mult of 8
- sub ecx, eax // drop over bytes from original length
- mov MMXLength, ecx
- } // end _asm block
- // Now do the math for the rest of the row
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000000000ffffff;
- ActiveMaskEnd.use = 0xffff000000000000;
- ShiftBpp.use = 24; // == bpp(3) * 8
- ShiftRem.use = 40; // == 64 - 24
- _asm
- {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dpth3lp:
- psrlq mm1, ShiftRem // shift last 3 bytes to 1st 3 bytes
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm1, mm0 // Unpack High bytes of a
- movq mm3, [esi+ebx-8] // Prep c=Prior(x-bpp) bytes
- punpcklbw mm2, mm0 // Unpack High bytes of b
- psrlq mm3, ShiftRem // shift last 3 bytes to 1st 3 bytes
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpcklbw mm3, mm0 // Unpack High bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx] // load c=Prior(x-bpp)
- pand mm7, ActiveMask
- movq mm2, mm3 // load b=Prior(x) step 1
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- punpcklbw mm3, mm0 // Unpack High bytes of c
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp)
- // Now do Paeth for 2nd set of bytes (3-5)
- psrlq mm2, ShiftBpp // load b=Prior(x) step 2
- punpcklbw mm1, mm0 // Unpack High bytes of a
- pxor mm7, mm7
- punpcklbw mm2, mm0 // Unpack High bytes of b
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- psubw mm5, mm3
- psubw mm4, mm3
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
- // pav + pbv = pbv + pav
- movq mm6, mm5
- paddw mm6, mm4
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm5 // Create mask pbv bytes < 0
- pcmpgtw mm7, mm4 // Create mask pav bytes < 0
- pand mm0, mm5 // Only pbv bytes < 0 in mm0
- pand mm7, mm4 // Only pav bytes < 0 in mm7
- psubw mm5, mm0
- psubw mm4, mm7
- psubw mm5, mm0
- psubw mm4, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- movq mm2, [esi + ebx] // load b=Prior(x)
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, mm2 // load c=Prior(x-bpp) step 1
- pand mm7, ActiveMask
- punpckhbw mm2, mm0 // Unpack High bytes of b
- psllq mm7, ShiftBpp // Shift bytes to 2nd group of 3 bytes
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- psllq mm3, ShiftBpp // load c=Prior(x-bpp) step 2
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, mm7
- punpckhbw mm3, mm0 // Unpack High bytes of c
- psllq mm1, ShiftBpp // Shift bytes
- // Now mm1 will be used as Raw(x-bpp)
- // Now do Paeth for 3rd, and final, set of bytes (6-7)
- pxor mm7, mm7
- punpckhbw mm1, mm0 // Unpack High bytes of a
- psubw mm4, mm3
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- pxor mm0, mm0
- paddw mm6, mm5
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- pandn mm0, mm1
- pandn mm7, mm4
- paddw mm0, mm2
- paddw mm7, mm5
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm1, mm1
- packuswb mm1, mm7
- // Step ebx to next set of 8 bytes and repeat loop til done
- add ebx, 8
- pand mm1, ActiveMaskEnd
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- pxor mm0, mm0 // pxor does not affect flags
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- // mm3 ready to be used as Prior(x-bpp) next loop
- jb dpth3lp
- } // end _asm block
- }
- break;
- case 6:
- case 7:
- case 5:
- {
- ActiveMask.use = 0x00000000ffffffff;
- ActiveMask2.use = 0xffffffff00000000;
- ShiftBpp.use = bpp << 3; // == bpp * 8
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm
- {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- pxor mm0, mm0
- dpth6lp:
- // Must shift to position Raw(x-bpp) data
- psrlq mm1, ShiftRem
- // Do first set of 4 bytes
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- punpcklbw mm1, mm0 // Unpack Low bytes of a
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm2, mm0 // Unpack Low bytes of b
- // Must shift to position Prior(x-bpp) data
- psrlq mm3, ShiftRem
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpcklbw mm3, mm0 // Unpack Low bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx - 8] // load c=Prior(x-bpp)
- pand mm7, ActiveMask
- psrlq mm3, ShiftRem
- movq mm2, [esi + ebx] // load b=Prior(x) step 1
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- movq mm6, mm2
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, [edi+ebx-8]
- psllq mm6, ShiftBpp
- movq mm5, mm7
- psrlq mm1, ShiftRem
- por mm3, mm6
- psllq mm5, ShiftBpp
- punpckhbw mm3, mm0 // Unpack High bytes of c
- por mm1, mm5
- // Do second set of 4 bytes
- punpckhbw mm2, mm0 // Unpack High bytes of b
- punpckhbw mm1, mm0 // Unpack High bytes of a
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- // Step ex to next set of 8 bytes and repeat loop til done
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- jb dpth6lp
- } // end _asm block
- }
- break;
- case 4:
- {
- ActiveMask.use = 0x00000000ffffffff;
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8] // Only time should need to read
- // a=Raw(x-bpp) bytes
- dpth4lp:
- // Do first set of 4 bytes
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- punpckhbw mm1, mm0 // Unpack Low bytes of a
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm2, mm0 // Unpack High bytes of b
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpckhbw mm3, mm0 // Unpack High bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx] // load c=Prior(x-bpp)
- pand mm7, ActiveMask
- movq mm2, mm3 // load b=Prior(x) step 1
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- punpcklbw mm3, mm0 // Unpack High bytes of c
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp)
- // Do second set of 4 bytes
- punpckhbw mm2, mm0 // Unpack Low bytes of b
- punpcklbw mm1, mm0 // Unpack Low bytes of a
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- // Step ex to next set of 8 bytes and repeat loop til done
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- jb dpth4lp
- } // end _asm block
- }
- break;
- case 8: // bpp == 8
- {
- ActiveMask.use = 0x00000000ffffffff;
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8] // Only time should need to read
- // a=Raw(x-bpp) bytes
- dpth8lp:
- // Do first set of 4 bytes
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- punpcklbw mm1, mm0 // Unpack Low bytes of a
- movq mm2, [esi + ebx] // load b=Prior(x)
- punpcklbw mm2, mm0 // Unpack Low bytes of b
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- punpcklbw mm3, mm0 // Unpack Low bytes of c
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes
- pand mm7, ActiveMask
- movq mm2, [esi + ebx] // load b=Prior(x)
- paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x)
- punpckhbw mm3, mm0 // Unpack High bytes of c
- movq [edi + ebx], mm7 // write back updated value
- movq mm1, [edi+ebx-8] // read a=Raw(x-bpp) bytes
- // Do second set of 4 bytes
- punpckhbw mm2, mm0 // Unpack High bytes of b
- punpckhbw mm1, mm0 // Unpack High bytes of a
- // pav = p - a = (a + b - c) - a = b - c
- movq mm4, mm2
- // pbv = p - b = (a + b - c) - b = a - c
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- movq mm6, mm4
- psubw mm5, mm3
- // pa = abs(p-a) = abs(pav)
- // pb = abs(p-b) = abs(pbv)
- // pc = abs(p-c) = abs(pcv)
- pcmpgtw mm0, mm4 // Create mask pav bytes < 0
- paddw mm6, mm5
- pand mm0, mm4 // Only pav bytes < 0 in mm7
- pcmpgtw mm7, mm5 // Create mask pbv bytes < 0
- psubw mm4, mm0
- pand mm7, mm5 // Only pbv bytes < 0 in mm0
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 // Create mask pcv bytes < 0
- pand mm0, mm6 // Only pav bytes < 0 in mm7
- psubw mm5, mm7
- psubw mm6, mm0
- // test pa <= pb
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 // pa > pb?
- movq mm0, mm7
- // use mm7 mask to merge pa & pb
- pand mm5, mm7
- // use mm0 mask copy to merge a & b
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- // test ((pa <= pb)? pa:pb) <= pc
- pcmpgtw mm7, mm6 // pab > pc?
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- // Step ex to next set of 8 bytes and repeat loop til done
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 // write back updated value
- // mm1 will be used as Raw(x-bpp) next loop
- jb dpth8lp
- } // end _asm block
- }
- break;
- case 1: // bpp = 1
- case 2: // bpp = 2
- default: // bpp > 8
- {
- _asm {
- mov ebx, diff
- cmp ebx, FullLength
- jnb dpthdend
- mov edi, row
- mov esi, prev_row
- // Do Paeth decode for remaining bytes
- mov edx, ebx
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // Set edx = ebx - bpp
- dpthdlp:
- xor eax, eax
- // pav = p - a = (a + b - c) - a = b - c
- mov al, [esi + ebx] // load Prior(x) into al
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- sub eax, ecx // subtract Prior(x-bpp)
- mov patemp, eax // Save pav for later use
- xor eax, eax
- // pbv = p - b = (a + b - c) - b = a - c
- mov al, [edi + edx] // load Raw(x-bpp) into al
- sub eax, ecx // subtract Prior(x-bpp)
- mov ecx, eax
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- add eax, patemp // pcv = pav + pbv
- // pc = abs(pcv)
- test eax, 0x80000000
- jz dpthdpca
- neg eax // reverse sign of neg values
- dpthdpca:
- mov pctemp, eax // save pc for later use
- // pb = abs(pbv)
- test ecx, 0x80000000
- jz dpthdpba
- neg ecx // reverse sign of neg values
- dpthdpba:
- mov pbtemp, ecx // save pb for later use
- // pa = abs(pav)
- mov eax, patemp
- test eax, 0x80000000
- jz dpthdpaa
- neg eax // reverse sign of neg values
- dpthdpaa:
- mov patemp, eax // save pa for later use
- // test if pa <= pb
- cmp eax, ecx
- jna dpthdabb
- // pa > pb; now test if pb <= pc
- cmp ecx, pctemp
- jna dpthdbbc
- // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthdpaeth
- dpthdbbc:
- // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
- mov cl, [esi + ebx] // load Prior(x) into cl
- jmp dpthdpaeth
- dpthdabb:
- // pa <= pb; now test if pa <= pc
- cmp eax, pctemp
- jna dpthdabc
- // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthdpaeth
- dpthdabc:
- // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
- mov cl, [edi + edx] // load Raw(x-bpp) into cl
- dpthdpaeth:
- inc ebx
- inc edx
- // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
- add [edi + ebx - 1], cl
- cmp ebx, FullLength
- jb dpthdlp
- dpthdend:
- } // end _asm block
- }
- return; // No need to go further with this one
- } // end switch ( bpp )
- _asm
- {
- // MMX acceleration complete now do clean-up
- // Check if any remaining bytes left to decode
- mov ebx, MMXLength
- cmp ebx, FullLength
- jnb dpthend
- mov edi, row
- mov esi, prev_row
- // Do Paeth decode for remaining bytes
- mov edx, ebx
- xor ecx, ecx // zero ecx before using cl & cx in loop below
- sub edx, bpp // Set edx = ebx - bpp
- dpthlp2:
- xor eax, eax
- // pav = p - a = (a + b - c) - a = b - c
- mov al, [esi + ebx] // load Prior(x) into al
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- sub eax, ecx // subtract Prior(x-bpp)
- mov patemp, eax // Save pav for later use
- xor eax, eax
- // pbv = p - b = (a + b - c) - b = a - c
- mov al, [edi + edx] // load Raw(x-bpp) into al
- sub eax, ecx // subtract Prior(x-bpp)
- mov ecx, eax
- // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
- add eax, patemp // pcv = pav + pbv
- // pc = abs(pcv)
- test eax, 0x80000000
- jz dpthpca2
- neg eax // reverse sign of neg values
- dpthpca2:
- mov pctemp, eax // save pc for later use
- // pb = abs(pbv)
- test ecx, 0x80000000
- jz dpthpba2
- neg ecx // reverse sign of neg values
- dpthpba2:
- mov pbtemp, ecx // save pb for later use
- // pa = abs(pav)
- mov eax, patemp
- test eax, 0x80000000
- jz dpthpaa2
- neg eax // reverse sign of neg values
- dpthpaa2:
- mov patemp, eax // save pa for later use
- // test if pa <= pb
- cmp eax, ecx
- jna dpthabb2
- // pa > pb; now test if pb <= pc
- cmp ecx, pctemp
- jna dpthbbc2
- // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth2
- dpthbbc2:
- // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
- mov cl, [esi + ebx] // load Prior(x) into cl
- jmp dpthpaeth2
- dpthabb2:
- // pa <= pb; now test if pa <= pc
- cmp eax, pctemp
- jna dpthabc2
- // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
- mov cl, [esi + edx] // load Prior(x-bpp) into cl
- jmp dpthpaeth2
- dpthabc2:
- // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
- mov cl, [edi + edx] // load Raw(x-bpp) into cl
- dpthpaeth2:
- inc ebx
- inc edx
- // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
- add [edi + ebx - 1], cl
- cmp ebx, FullLength
- jb dpthlp2
- dpthend:
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized code for PNG Sub filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
- {
- //int test;
- int bpp;
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- int diff;
- bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
- FullLength = row_info->rowbytes - bpp; // # of bytes to filter
- _asm {
- mov edi, row
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- xor eax, eax
- // get # of bytes to alignment
- mov diff, edi // take start of row
- add diff, 0xf // add 7 + 8 to incr past
- // alignment boundary
- xor ebx, ebx
- and diff, 0xfffffff8 // mask to alignment boundary
- sub diff, edi // subtract from start ==> value
- // ebx at alignment
- jz dsubgo
- // fix alignment
- dsublp1:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, diff
- jb dsublp1
- dsubgo:
- mov ecx, FullLength
- mov edx, ecx
- sub edx, ebx // subtract alignment fix
- and edx, 0x00000007 // calc bytes over mult of 8
- sub ecx, edx // drop over bytes from length
- mov MMXLength, ecx
- } // end _asm block
- // Now do the math for the rest of the row
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000ffffff000000;
- ShiftBpp.use = 24; // == 3 * 8
- ShiftRem.use = 40; // == 64 - 24
- _asm {
- mov edi, row
- movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- movq mm6, mm7
- mov ebx, diff
- psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active
- // byte group
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dsub3lp:
- psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
- // no need for mask; shift clears inactive bytes
- // Add 1st active group
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- // Add 2nd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm7 // mask to use only 2nd active group
- paddb mm0, mm1
- // Add 3rd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm6 // mask to use only 3rd active group
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // Write updated Raws back to array
- // Prep for doing 1st add at top of loop
- movq mm1, mm0
- jb dsub3lp
- } // end _asm block
- }
- break;
- case 1:
- {
- // Placed here just in case this is a duplicate of the
- // non-MMX code for the SUB filter in png_read_filter_row below
- //
- // png_bytep rp;
- // png_bytep lp;
- // png_uint_32 i;
- // bpp = (row_info->pixel_depth + 7) >> 3;
- // for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
- // i < row_info->rowbytes; i++, rp++, lp++)
- // {
- // *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
- // }
- _asm {
- mov ebx, diff
- mov edi, row
- cmp ebx, FullLength
- jnb dsub1end
- mov esi, edi // lp = row
- xor eax, eax
- add edi, bpp // rp = row + bpp
- dsub1lp:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, FullLength
- jb dsub1lp
- dsub1end:
- } // end _asm block
- }
- return;
- case 6:
- case 7:
- case 4:
- case 5:
- {
- ShiftBpp.use = bpp << 3;
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm {
- mov edi, row
- mov ebx, diff
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dsub4lp:
- psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
- // no need for mask; shift clears inactive bytes
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- // Add 2nd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- // there is no need for any mask
- // since shift clears inactive bits/bytes
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0
- movq mm1, mm0 // Prep for doing 1st add at top of loop
- jb dsub4lp
- } // end _asm block
- }
- break;
- case 2:
- {
- ActiveMask.use = 0x00000000ffff0000;
- ShiftBpp.use = 16; // == 2 * 8
- ShiftRem.use = 48; // == 64 - 16
- _asm {
- movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group
- mov ebx, diff
- movq mm6, mm7
- mov edi, row
- psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active
- // byte group
- mov esi, edi // lp = row
- movq mm5, mm6
- add edi, bpp // rp = row + bpp
- psllq mm5, ShiftBpp // Move mask in mm5 to cover 4th active
- // byte group
- // PRIME the pump (load the first Raw(x-bpp) data set
- movq mm1, [edi+ebx-8]
- dsub2lp:
- // Add 1st active group
- psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
- // no need for mask; shift clears inactive
- // bytes
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- // Add 2nd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm7 // mask to use only 2nd active group
- paddb mm0, mm1
- // Add 3rd active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm6 // mask to use only 3rd active group
- paddb mm0, mm1
- // Add 4th active group
- movq mm1, mm0 // mov updated Raws to mm1
- psllq mm1, ShiftBpp // shift data to position correctly
- pand mm1, mm5 // mask to use only 4th active group
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // Write updated Raws back to array
- movq mm1, mm0 // Prep for doing 1st add at top of loop
- jb dsub2lp
- } // end _asm block
- }
- break;
- case 8:
- {
- _asm {
- mov edi, row
- mov ebx, diff
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- mov ecx, MMXLength
- movq mm7, [edi+ebx-8] // PRIME the pump (load the first
- // Raw(x-bpp) data set
- and ecx, 0x0000003f // calc bytes over mult of 64
- dsub8lp:
- movq mm0, [edi+ebx] // Load Sub(x) for 1st 8 bytes
- paddb mm0, mm7
- movq mm1, [edi+ebx+8] // Load Sub(x) for 2nd 8 bytes
- movq [edi+ebx], mm0 // Write Raw(x) for 1st 8 bytes
- // Now mm0 will be used as Raw(x-bpp) for
- // the 2nd group of 8 bytes. This will be
- // repeated for each group of 8 bytes with
- // the 8th group being used as the Raw(x-bpp)
- // for the 1st group of the next loop.
- paddb mm1, mm0
- movq mm2, [edi+ebx+16] // Load Sub(x) for 3rd 8 bytes
- movq [edi+ebx+8], mm1 // Write Raw(x) for 2nd 8 bytes
- paddb mm2, mm1
- movq mm3, [edi+ebx+24] // Load Sub(x) for 4th 8 bytes
- movq [edi+ebx+16], mm2 // Write Raw(x) for 3rd 8 bytes
- paddb mm3, mm2
- movq mm4, [edi+ebx+32] // Load Sub(x) for 5th 8 bytes
- movq [edi+ebx+24], mm3 // Write Raw(x) for 4th 8 bytes
- paddb mm4, mm3
- movq mm5, [edi+ebx+40] // Load Sub(x) for 6th 8 bytes
- movq [edi+ebx+32], mm4 // Write Raw(x) for 5th 8 bytes
- paddb mm5, mm4
- movq mm6, [edi+ebx+48] // Load Sub(x) for 7th 8 bytes
- movq [edi+ebx+40], mm5 // Write Raw(x) for 6th 8 bytes
- paddb mm6, mm5
- movq mm7, [edi+ebx+56] // Load Sub(x) for 8th 8 bytes
- movq [edi+ebx+48], mm6 // Write Raw(x) for 7th 8 bytes
- add ebx, 64
- paddb mm7, mm6
- cmp ebx, ecx
- movq [edi+ebx-8], mm7 // Write Raw(x) for 8th 8 bytes
- jb dsub8lp
- cmp ebx, MMXLength
- jnb dsub8lt8
- dsub8lpA:
- movq mm0, [edi+ebx]
- add ebx, 8
- paddb mm0, mm7
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // use -8 to offset early add to ebx
- movq mm7, mm0 // Move calculated Raw(x) data to mm1 to
- // be the new Raw(x-bpp) for the next loop
- jb dsub8lpA
- dsub8lt8:
- } // end _asm block
- }
- break;
- default: // bpp greater than 8 bytes
- {
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, edi // lp = row
- add edi, bpp // rp = row + bpp
- dsubAlp:
- movq mm0, [edi+ebx]
- movq mm1, [esi+ebx]
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 // mov does not affect flags; -8 to offset
- // add ebx
- jb dsubAlp
- } // end _asm block
- }
- break;
- } // end switch ( bpp )
- _asm {
- mov ebx, MMXLength
- mov edi, row
- cmp ebx, FullLength
- jnb dsubend
- mov esi, edi // lp = row
- xor eax, eax
- add edi, bpp // rp = row + bpp
- dsublp2:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, FullLength
- jb dsublp2
- dsubend:
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized code for PNG Up filter decoder
- void /* PRIVATE */
- png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
- png_bytep prev_row)
- {
- png_uint_32 len;
- len = row_info->rowbytes; // # of bytes to filter
- _asm {
- mov edi, row
- // get # of bytes to alignment
- mov ecx, edi
- xor ebx, ebx
- add ecx, 0x7
- xor eax, eax
- and ecx, 0xfffffff8
- mov esi, prev_row
- sub ecx, edi
- jz dupgo
- // fix alignment
- duplp1:
- mov al, [edi+ebx]
- add al, [esi+ebx]
- inc ebx
- cmp ebx, ecx
- mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
- jb duplp1
- dupgo:
- mov ecx, len
- mov edx, ecx
- sub edx, ebx // subtract alignment fix
- and edx, 0x0000003f // calc bytes over mult of 64
- sub ecx, edx // drop over bytes from length
- // Unrolled loop - use all MMX registers and interleave to reduce
- // number of branch instructions (loops) and reduce partial stalls
- duploop:
- movq mm1, [esi+ebx]
- movq mm0, [edi+ebx]
- movq mm3, [esi+ebx+8]
- paddb mm0, mm1
- movq mm2, [edi+ebx+8]
- movq [edi+ebx], mm0
- paddb mm2, mm3
- movq mm5, [esi+ebx+16]
- movq [edi+ebx+8], mm2
- movq mm4, [edi+ebx+16]
- movq mm7, [esi+ebx+24]
- paddb mm4, mm5
- movq mm6, [edi+ebx+24]
- movq [edi+ebx+16], mm4
- paddb mm6, mm7
- movq mm1, [esi+ebx+32]
- movq [edi+ebx+24], mm6
- movq mm0, [edi+ebx+32]
- movq mm3, [esi+ebx+40]
- paddb mm0, mm1
- movq mm2, [edi+ebx+40]
- movq [edi+ebx+32], mm0
- paddb mm2, mm3
- movq mm5, [esi+ebx+48]
- movq [edi+ebx+40], mm2
- movq mm4, [edi+ebx+48]
- movq mm7, [esi+ebx+56]
- paddb mm4, mm5
- movq mm6, [edi+ebx+56]
- movq [edi+ebx+48], mm4
- add ebx, 64
- paddb mm6, mm7
- cmp ebx, ecx
- movq [edi+ebx-8], mm6 // (+56)movq does not affect flags;
- // -8 to offset add ebx
- jb duploop
- cmp edx, 0 // Test for bytes over mult of 64
- jz dupend
- // 2 lines added by lcreeve at netins.net
- // (mail 11 Jul 98 in png-implement list)
- cmp edx, 8 //test for less than 8 bytes
- jb duplt8
- add ecx, edx
- and edx, 0x00000007 // calc bytes over mult of 8
- sub ecx, edx // drop over bytes from length
- jz duplt8
- // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously
- duplpA:
- movq mm1, [esi+ebx]
- movq mm0, [edi+ebx]
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, ecx
- movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx
- jb duplpA
- cmp edx, 0 // Test for bytes over mult of 8
- jz dupend
- duplt8:
- xor eax, eax
- add ecx, edx // move over byte count into counter
- // Loop using x86 registers to update remaining bytes
- duplp2:
- mov al, [edi + ebx]
- add al, [esi + ebx]
- inc ebx
- cmp ebx, ecx
- mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
- jb duplp2
- dupend:
- // Conversion of filtered row completed
- emms // End MMX instructions; prep for possible FP instrs.
- } // end _asm block
- }
- // Optimized png_read_filter_row routines
- void /* PRIVATE */
- png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
- row, png_bytep prev_row, int filter)
- {
- #ifdef PNG_DEBUG
- char filnm[10];
- #endif
- if (mmx_supported == 2) {
- #if !defined(PNG_1_0_X)
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- #endif
- png_mmx_support();
- }
- #ifdef PNG_DEBUG
- png_debug(1, "in png_read_filter_rown");
- switch (filter)
- {
- case 0: sprintf(filnm, "none");
- break;
- #if !defined(PNG_1_0_X)
- case 1: sprintf(filnm, "sub-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86");
- break;
- case 2: sprintf(filnm, "up-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86");
- break;
- case 3: sprintf(filnm, "avg-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86");
- break;
- case 4: sprintf(filnm, "Paeth-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86");
- break;
- #else
- case 1: sprintf(filnm, "sub");
- break;
- case 2: sprintf(filnm, "up");
- break;
- case 3: sprintf(filnm, "avg");
- break;
- case 4: sprintf(filnm, "Paeth");
- break;
- #endif
- default: sprintf(filnm, "unknw");
- break;
- }
- png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
- png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
- (int)((row_info->pixel_depth + 7) >> 3));
- png_debug1(0,"len=%8d, ", row_info->rowbytes);
- #endif /* PNG_DEBUG */
- switch (filter)
- {
- case PNG_FILTER_VALUE_NONE:
- break;
- case PNG_FILTER_VALUE_SUB:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_sub(row_info, row);
- }
- else
- {
- png_uint_32 i;
- png_uint_32 istop = row_info->rowbytes;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_bytep rp = row + bpp;
- png_bytep lp = row;
- for (i = bpp; i < istop; i++)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
- rp++;
- }
- }
- break;
- }
- case PNG_FILTER_VALUE_UP:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_up(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_uint_32 istop = row_info->rowbytes;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- for (i = 0; i < istop; ++i)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
- rp++;
- }
- }
- break;
- }
- case PNG_FILTER_VALUE_AVG:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_avg(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- png_bytep lp = row;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_uint_32 istop = row_info->rowbytes - bpp;
- for (i = 0; i < bpp; i++)
- {
- *rp = (png_byte)(((int)(*rp) +
- ((int)(*pp++) >> 1)) & 0xff);
- rp++;
- }
- for (i = 0; i < istop; i++)
- {
- *rp = (png_byte)(((int)(*rp) +
- ((int)(*pp++ + *lp++) >> 1)) & 0xff);
- rp++;
- }
- }
- break;
- }
- case PNG_FILTER_VALUE_PAETH:
- {
- #if !defined(PNG_1_0_X)
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- #else
- if (mmx_supported)
- #endif
- {
- png_read_filter_row_mmx_paeth(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- png_bytep lp = row;
- png_bytep cp = prev_row;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_uint_32 istop=row_info->rowbytes - bpp;
- for (i = 0; i < bpp; i++)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
- rp++;
- }
- for (i = 0; i < istop; i++) // use leftover rp,pp
- {
- int a, b, c, pa, pb, pc, p;
- a = *lp++;
- b = *pp++;
- c = *cp++;
- p = b - c;
- pc = a - c;
- #ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
- #else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
- #endif
- /*
- if (pa <= pb && pa <= pc)
- p = a;
- else if (pb <= pc)
- p = b;
- else
- p = c;
- */
- p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
- *rp = (png_byte)(((int)(*rp) + p) & 0xff);
- rp++;
- }
- }
- break;
- }
- default:
- png_warning(png_ptr, "Ignoring bad row filter type");
- *row=0;
- break;
- }
- }
- #endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */