📄 alphablend.asm
字号:
;
; ***** 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -