alphablend.asm
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:8k
- ;
- ; ***** BEGIN LICENSE BLOCK *****
- ; Version: RCSL 1.0/RPSL 1.0
- ;
- ; Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- ;
- ; The contents of this file, and the files included with this file, are
- ; subject to the current version of the RealNetworks Public Source License
- ; Version 1.0 (the "RPSL") available at
- ; http://www.helixcommunity.org/content/rpsl unless you have licensed
- ; the file under the RealNetworks Community Source License Version 1.0
- ; (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- ; in which case the RCSL will apply. You may also obtain the license terms
- ; directly from RealNetworks. You may not use this file except in
- ; compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- ; applicable to this file, the RCSL. Please see the applicable RPSL or
- ; RCSL for the rights, obligations and limitations governing use of the
- ; contents of the file.
- ;
- ; This file is part of the Helix DNA Technology. RealNetworks is the
- ; developer of the Original Code and owns the copyrights in the portions
- ; it created.
- ;
- ; This file, and the files included with this file, is distributed and made
- ; available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- ; EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- ; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- ; FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- ;
- ; Technology Compatibility Kit Test Suite(s) Location:
- ; http://www.helixcommunity.org/content/tck
- ;
- ; Contributor(s):
- ;
- ; ***** END LICENSE BLOCK *****
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; alphablend.asm
- ;;
- ;;
- ;; Alpha blend two ARGB images. Put result back into top image.
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- %ifdef COFF
- %define AlphaBlendMMX _AlphaBlendMMX
- %elifdef WIN32
- %define AlphaBlendMMX _AlphaBlendMMX
- %elifdef ELF
- %define AlphaBlendMMX AlphaBlendMMX
- %elifdef AOUTB
- %define AlphaBlendMMX AlphaBlendMMX
- %else
- %error linking format currently not supported by alphbablend.asm
- %endif
- global AlphaBlendMMX
- ; %include "standard.inc"
- section .data
- section .text
- ;;;
- ;;; void AlphaBlendMMX(unsigned char* p_top, unsigned char* p_bot, int size)
- ;;; copy bottom into top.
- ;;;
- ;;; we *MUST* preserve the top pixel alpha channel. This is used for
- ;;; transparent hit testing.
- AlphaBlendMMX:
-
- ;; Figure stack out.....
- struc parms
- resd 4 ; Register and return address
- .p_top: resd 1 ; UCHAR* p_bot
- .p_bot: resd 1 ; UCHAR* p_bot
- .size: resd 1 ; int size
- endstruc
-
- ;; Save some stuff...
- push ebx
- push edi
- push esi
- ;; Get size.
- mov esi, [esp+parms.p_top]
- mov edi, [esp+parms.p_bot]
- mov eax, [esp+parms.size]
- mov ecx, 8 ; preload the additive constant
- pxor mm7, mm7
- pcmpeqw mm6, mm6 ; For inverting the alpha channel
-
- movq mm2, [esi] ; mm2 = a2r2 g2b2 a1r1 g1b1 Top (P)
- psrlw mm6, 8 ; mm6 = 00ff 00ff 00ff 00ff
- movq mm3, [edi] ; mm3 = a2r2 g2b2 a1r1 g1b1 Bot (Q)
- shr eax, 1 ; We only loop 1/2 the count.
- jz NEAR L2 ; skip if we only have 1 or no pixels.
- L1: movq mm0,mm2 ; mm0 = a2r2 g2b2 a1r1 g1b1 Top (P)
- movq mm1,mm3 ; mm1 = a2r2 g2b2 a1r1 g1b1 Bot (Q)
- punpcklbw mm0,mm7 ; mm0 = 00pa 00pr 00pg 00pb 1st pixel
- punpcklbw mm1,mm7 ; mm1 = 00qa 00qr 00qg 00qb 1st pixel
- ;; Prefetch next data needed....
- ; prefetchnta [esi+16] ; This is only on >PIII
- movq mm4,mm0 ; mm4 = 00pa 00xx 00xx 00xx 1st pixel
- punpckhbw mm2,mm7 ; mm2 = 00pa 00pr 00pg 00pb 2nd pixel
- psubw mm0,mm1 ; mm0 = P-Q (never mind alpha values) 1st pixel
- punpckhbw mm3,mm7 ; mm3 = 00qa 00qr 00qg 00qb 2nd pixel
- ; spread pa1,pa2 alpha to all channels;
- movq mm5,mm2 ; mm5 = 00pa 00pr 00pg 00pb 2nd pixel
- punpckhwd mm4,mm4 ; mm4 = 00pa 00pa xxxx xxxx 1st pixel
- psubw mm2,mm3 ; mm2 = P-Q (never mind alpha values) 2nd pixel
- punpckhwd mm5,mm5 ; mm5 = 00pa 00pa xxxx xxxx 2nd pixel
- add esi,ecx ; esi += 8
- punpckhdq mm4,mm4 ; mm4 = 00pa 00pa 00pa 00pa 1st pixel
- add edi,ecx ; edi += 8
- punpckhdq mm5,mm5 ; mm5 = 00pa 00pa 00pa 00pa 2nd pixel
- ;; Invert Alpha channel because we output backwards from the
- ;; renderers
- pandn mm4, mm6
- pandn mm5, mm6
- ;; Prefetch next data needed....
- ; prefetchnta [edi+8];this is only on >PIII
- pmullw mm0, mm4 ; mm0 = (P-Q)*alpha 1st pixel
- pmullw mm2, mm5 ; mm2 = (P-Q)*alpha 2nd pixel
- dec eax ; decrement loop counter.
-
- psllw mm1, 8 ; mm1 = 256Q
- psllw mm3, 8 ; mm3 = 256Q
- paddw mm1, mm0 ; mm1 = 256Q + (P-Q)*alpha 1st pixel
- paddw mm3, mm2 ; mm3 = 256Q + (P-Q)*alpha 2nd pixel
- psrlw mm1, 8 ; mm1 = (256Q + (P-Q)*alpha)/256 1st pixel
- psrlw mm3, 8 ; mm3 = (256Q + (P-Q)*alpha)/256 2nd pixel
- jz L5
-
- movq mm2,[esi]
- packuswb mm1,mm3 ; mm1 = 00r2 g2b2 00r1 g1b1 NEW Top (P)
- pandn mm4, mm6 ; invert the alpha channel again to get original
- pandn mm5, mm6 ; invert the alpha channel again to get original
- packuswb mm4, mm5 ; mm4 = qaqa qaqa papa papa
- pslld mm4, 24 ; mm4 = qa00 0000 pa00 0000
- por mm1, mm4 ; mm1 = a2r2 g2b2 a1r1 g1b1
- movq mm3,[edi]
- movq [esi-8],mm1
- jmp L1
- L5:
- packuswb mm1,mm3 ; mm1 = 00r2 g2b2 00r1 g1b1 NEW Top (P)
- pandn mm4, mm6 ; invert the alpha channel again to get original
- pandn mm5, mm6 ; invert the alpha channel again to get original
- packuswb mm4, mm5 ; mm4 = qaqa qaqa papa papa
- pslld mm4, 24 ; mm4 = qa00 0000 pa00 0000
- por mm1, mm4 ; mm1 = a2r2 g2b2 a1r1 g1b1
- movq [esi-8],mm1
-
- ;;; If there were an odd number of pixels, do the odd
- ;;; one here
- L2:
- mov eax,[esp+parms.size]; Get the original count again.
- shr eax,1
- jnc L3 ; skip if there was no odd pixel.
- ;; mm2 and mm3 have the single pixel in their LSB double
- ;; words now.
- movd mm2, [esi] ; mm2 = xxxx xxxx a1r1 g1b1 Top
- movd mm3, [edi] ; mm3 = xxxx xxxx a1r1 g1b1 Bottom
- punpcklbw mm2,mm7 ; mm2 = 00pa 00pr 00pg 00pb
- punpcklbw mm3,mm7 ; mm3 = 00qa 00qr 00qg 00qb
- movq mm4,mm2 ; mm4 = 00pa 00xx 00xx 00xx
- psubw mm2,mm3 ; mm2 = P-Q (never mind alpha values)
- ; spread pa1,pa2 alpha to all channels;
- punpckhwd mm4,mm4 ; mm4 = 00pa 00pa xxxx xxxx
- punpckhdq mm4,mm4 ; mm4 = 00pa 00pa 00pa 00pa
- ;; Invert Alpha channel because we output backwards from the
- ;; renderers
- pandn mm4, mm6
- pmullw mm2, mm4 ; mm2 = (P-Q)*alpha
- psllw mm3, 8 ; mm3 = 256Q
- paddw mm3, mm2 ; mm3 = 256Q + (P-Q)*alpha
- psrlw mm3, 8 ; mm3 = (256Q + (P-Q)*alpha)/256
- packuswb mm3,mm7
-
- pandn mm4, mm6 ; invert the alpha channel again to get original
- pslld mm4, 24 ; mm4 = pa00 0000 pa00 0000
- por mm3, mm4 ; mm3 = a2r2 g2b2 a1r1 g1b1
- movd [esi], mm3 ; store it.
-
- ;;; Restore and return.
- L3:
- ;; No emms instruction. Done in outer loop
- ;; Pop off the stack....
- pop esi
- pop edi
- pop ebx
-
- ret ; Get out...
- ;;; leave a trace
- version: db '@(#) $ RealNetworks Revision: .9 $',0