| ||
The following code is a sample of a transparent blit, where a scanline of a count of ECX 8-bit bytes is copied from one graphic source row [ESI] to a destination graphic row [EDI] one pixel at a time.
This eight 8-bit transparent pixel copy uses MMX code. Note that there is only one branch loop every eighth pixel.
tcolor qword 03f3f3f3f3f3f3f3fh ; 03fh = transparent pixel ; esi=source edi=destination ecx=# of qwords movq mm7,tcolor ; Get replicated transparency $T0: movq mm5,[esi] ; Get 8 source pixels movq mm4,[edi] ; Get background movq mm6,mm5 ; Copy 8 source pixels ; Compare each pixel's color to transparency color and if ; a match, set each pixel in the mask to FF else 00! pcmpeqb mm5,mm7 ; Create masks for transparency add esi,8 ; Adjust source pointer ; Only keep the pixels in the destination that correspond ; to the transparent pixels of the source! pand mm4,mm5 ; Using the same mask, flip it, then AND it with the ; source pixels, keeping the non-transparent pixels. pandn mm5,mm6 ; erase transparent pixels ; Or the destination pixels with the source pixels. por mm4,mm5 ; blend 8 pixels into art movq [edi],mm4 ; Save new background add edi,8 ; Adjust destination pointer dec ecx ; any pixels left? jne $T0 ; Loop for eight 8-bit pixels
There is no transparency testing or branching, only the masking and blending of data, which makes the process of a transparent blit much faster. These two different blits (copy, transparent) are typically designed for a graphic environment such as in Figure 19-5 where the background seen on the right is kept in a separate buffer like wallpaper.
The background is CopyBlit to the working surface as seen on the left, and the sprite image is Transparent Blit in front of it. When the sprite image is animated, the area being changed is "erased" from the working surface by a rectangular CopyBlit of that area from the background to the working surface and then the update sprite image has a rectangular area Transparent Blit in front. This is a layered approach typically used in a video game that has a number of animated objects moving around the display.
Another graphic sprite environment method is where the area under the sprite is remembered in a buffer attached to the sprite before the sprite image is Transparent Blit. This operation typically occurs simultaneously to reduce the amount of calculation work.
This is typically called an "overlay" method used by Windows and some sprite engines. The drawback to this method is that overlapping of sprites needs to be minimized because erasing one requires all the other intersecting sprites visible above that sprite to be erased. The list of sprites needs to be traversed to find out which sprites intersect the area and need to be erased and repainted by replacing the image under each intersecting sprite in the image buffer with the corresponding original background image. The list of sprites then needs to be traversed again, this time drawing the sprites back into the scene.
tcolor qword 03f3f3f3f3f3f3f3fh ; 03fh = transparent pixel ; esi=source edi=destination ebx=buffer ecx=# of qwords movq mm7,tcolor ; Get replicated transparency $T0: movq mm5,[esi] ; Get 8 source pixels movq mm4,[edi] ; Get 8 background pixels movq mm6,mm5 ; Copy 8 source pixels ; Compare each pixel's color to transparency color and if ; a match, set each pixel in the mask to FF, else 00! pcmpeqb mm5,mm7 ; Create masks for transparency movq [ebx],mm4 ; Save BGnd in buffer ; Only keep the pixels in the destination that correspond ; to the transparent pixels of the source! pand mm4,mm5 ; Using the same mask, flip it then AND it with the ; source pixels, keeping the non-transparent pixels. pandn mm5,mm6 ; erase transparent pixels ; Or the destination pixels with the source pixels. add ebx,8 ; Adjust buffer pointer por mm4,mm5 ; Blend 8 pixels into art add esi,8 ; Adjust source pointer movq [edi],mm4 ; Save new background add edi,8 ; Adjust destination pointer dec ecx ; Any pixels left? jne $T0 ; Loop for eight 8-bit pixels