kolibrios/kernel/branches/Kolibri-A/trunk/video/graph32.inc

1097 lines
31 KiB
PHP
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GRAPH32.INC ;;
;; ;;
;; 32bpp graph engine for Kolibri-A ;;
;; ;;
;; art_zh (kolibri@jerdev.co.uk) Dec. 2010 : ;;
;; - 4x2 granularity & tiled winmap structure ;;
;; - speed-optimized line/box graphics ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 1708 $
;*************************************************
; getpixel
;
; in:
; eax = x coordinate
; ebx = y coordinate
;
; ret:
; ecx = 00 RR GG BB
get_pixel:
mov ecx, [BytesPerScanLine]
imul ecx, ebx
lea ecx, [ecx+eax*4] ; ecx = x*4+(y*y multiplier)
mov ecx, [ecx+LFB_BASE]
and ecx, 0xffffff
ret
;-----------------------------------------------------------------------------------
; esi : Buffer origin
; edi : Screen origin
; ebp : Map origin
; ecx : block height (pix)
; ebx : bit[24] = odd line; bh = temp; bl = current task
align 4
draw_aligned_box:
pushad
xor edx, edx
.new_line:
btr ebx, 26
mov eax, [img_map_x]
xor ecx, ecx
cmp bl, byte[ebp] ; check the left tile first
je .new_tile
bts ebx, 26 ; ebx[26] = 1 if edi/esi pushed
push edi
push esi
push [img_bitoffset]
jmp .seek_visible
.new_tile:
inc ecx ; visible - scan the open space
cmp ecx, eax
jz .end_of_line
cmp bl, byte[ebp+ecx]
je .new_tile
; overlapped? draw the last visible segment if so
bts ebx, 26 ; check if edi/esi already pushed
jc @f
push edi
push esi
push [img_bitoffset]
@@: call [img_draw_core_fn] ; bpp-specific helper (see below)
.seek_visible:
inc ecx
cmp ecx, eax
je .next_line
cmp bl, byte[ebp+ecx]
jne .seek_visible
.got_visible:
sub eax, ecx
shl ecx, 4
add edi, ecx ; shift the left edge
bt ebx, 25 ; 1bpp?
jc @f
shr ecx, 2
imul ecx, [img_bytes_per_pix]
jmp .new_visible
@@: shr ecx, 8 ; 2 tiles = 1 byte
jnc .new_visible
rol [img_bitoffset], 4
jnc .new_visible
inc ecx
.new_visible:
add esi, ecx
xor ecx, ecx
jmp .new_tile
.end_of_line:
call [img_draw_core_fn]
.next_line:
bt ebx, 26
jnc @f
pop [img_bitoffset]
pop esi
pop edi
@@: inc edx
cmp edx, [esp+24] ; stacked ecx = image height
je .finish
add edi, [BytesPerScanLine]
add esi, [img_buf_line_size]
btc ebx, 24 ; odd line?
jnc .new_line
add ebp, [_WinMapWidth]
jmp .new_line
.finish:
popad
ret
;--------------------------------
; ebx : bit[24] = odd line; bh = reserved; bl = current task
; ecx : column height (pix)
; edx : max tile offset: 0, 4, 8, or 12 bytes (1,2,3 or 4 pix to draw)
; ebp : map origin
; esi : buffer image origin
; edi : LFB-origin (4byte-aligned)
align 4
draw_unaligned_edge:
pushad
mov eax, [img_buf_line_size]
mov bh, dl ; store the 1st tile offset
btr ebx, 24 ; check if the 1st line odd
jnc .new_tile
cmp bl, byte[ebp]
jne @f
call [img_draw_edge_fn] ; bpp-specific helper (see below)
@@:
dec ecx
jz .exit
add edi, [BytesPerScanLine]
add ebp, [_WinMapWidth]
add esi, eax
.new_tile:
cmp bl, byte[ebp]
jne .skip_tile
call [img_draw_edge_fn]
dec ecx
jz .exit
add edi, [BytesPerScanLine]
add esi, eax
call [img_draw_edge_fn]
dec ecx
jz .exit
add edi, [BytesPerScanLine]
add ebp, [_WinMapWidth]
add esi, eax
jmp .new_tile
.skip_tile:
sub cx, 2
jbe .exit
add edi, [BytesPerScanLine]
add edi, [BytesPerScanLine]
add esi, eax
add esi, eax
add ebp, [_WinMapWidth]
jmp .new_tile
.exit:
popad
ret
;-------------
; unaligned edge helpers
; esi -> left point of the image edge
; edi -> left point of the screen edge
; bh = edx = tile offset (0, 4, 8 or 12 bytes)
align 4
draw_edge_0bpp:
push eax
mov eax, [esi]
.putpix:
mov [edi+edx], eax
sub dl, 4
jae .putpix
.exit:
movzx edx, bh
pop eax
ret
align 4
draw_edge_32bpp:
push eax
.putpix:
mov eax, [esi+edx]
mov [edi+edx], eax
sub dl, 4
jae .putpix
.exit:
movzx edx, bh
pop eax
ret
align 4
draw_edge_24bpp:
push eax esi
xor dl, dl
.putpix:
mov eax, [esi]
and eax, 0x00FFFFFF
mov [edi+edx], eax
cmp dl, bh
je .exit
add dl, 4
add esi, 3
jmp .putpix
.exit:
pop esi eax
ret
align 4
draw_edge_8bpp:
push eax esi ebp
xor dl, dl
mov ebp, [img_palette]
.putpix:
movzx eax, byte[esi]
mov eax, [ebp+eax*4]
mov [edi+edx], eax
cmp dl, bh
je .exit
add dl, 4
inc esi
jmp .putpix
.exit:
pop ebp esi eax
ret
align 4
draw_edge_1bpp:
pushad
movzx edx, bh
add edx, edi
mov ebp, [img_palette]
mov ebx, [ebp+4] ; forecolor
mov ebp, [ebp] ; backcolor
mov ecx, [img_edgeoffset] ; cl = 1 << left_edge_pix_num
mov eax, [esi]
.testbit:
test eax, ecx
jnz @f
mov eax, ebp
jmp .putpix
@@: mov eax, ebx
.putpix:
mov [edi], eax
cmp edi, edx
je .exit
add edi, 4
rol ecx, 1
jmp .testbit
.exit:
popad
ret
draw_edge_16bpp:
draw_core_16bpp:
ret
;-------------
; aligned core helpers
; esi -> left point address (buffer)
; edi -> left point address (screen)
; ecx = number of tiles to draw
align 4
draw_core_0bpp:
push eax ecx edi
pushfd
; cli
cld
mov eax, [esi]
shl ecx, 2
rep stosd
popfd
pop edi ecx eax
ret
align 4
draw_core_32bpp:
push ecx esi edi
pushfd
; cli
cld
shl ecx, 2
rep movsd
popfd
pop edi esi ecx
ret
align 4
draw_core_24bpp:
push eax ecx edx
shl ecx, 2 ; ecx = numpixels
dec ecx
lea edx, [ecx*2+ecx] ; edx = buffer byte offset
.putpix:
mov eax, [esi+edx]
and eax, 0x00FFFFFF
mov [edi+ecx*4], eax
dec ecx
sub edx, 3
jnb .putpix
pop edx ecx eax
ret
align 4
draw_core_8bpp:
pushad
mov ebp, [img_palette]
.putpix:
xor edx, edx
mov eax, dword[esi] ; block of 4 pixels
.putone:
movzx ebx, al
mov ebx, [ebp+ebx*4]
mov [edi+edx*4], ebx
shr eax, 8
inc dl
cmp dl, 4
jnz .putone
add esi, edx ;-)
add edi, 16
dec ecx
jnz .putpix
.exit:
popad
ret
align 4
draw_core_1bpp:
pushad
mov ebp, [img_palette]
mov edx, [ebp+4] ; foreground color
mov ebp, [ebp] ; background color
mov ebx, [img_bitoffset]
shl ecx, 2 ; 1 tyle = 4 pix
.newblock:
mov eax, [esi]
.putpix:
test ebx, eax
jz .bkcolor
mov [edi], edx
jmp .nextpix
.bkcolor:
mov [edi], ebp
.nextpix:
dec ecx
jz .exit
rol ebx, 1
jc .nextblock
add edi, 4
jmp .putpix
.nextblock:
add esi, 4
jmp .newblock
.exit:
popad
ret
;-----------------------------------------
virtual at esp
putimg:
.image_sx dd ? ; X-size (pix)
.image_sy dd ? ; Y-size
.stack_data = 2*4
end virtual
align 4
; ebx -> Buffer origin
; ecx = packed size [x|y]
; edx = packed coordinates [x|y]
; static variables required:
; [img_draw_core_fn], [img_draw_edge_fn]
; [img_bytes_per_pix], [img_buf_line_size]
; [img_palette] (1bpp and 8bpp only)
_putimage:
; call [_display.disable_mouse]
pushad
sub esp, putimg.stack_data
mov [img_buf_origin], ebx ; save pointer to image buffer
mov esi, ebx ; pointer to image
.unpack_coords:
mov eax, ecx
and ecx, 0xFFFF ; Ysize
shr eax, 16 ; Xsize
mov [putimg.image_sy], ecx
mov [putimg.image_sx], eax
mov eax, edx
and edx, 0xFFFF ; Ytop
shr eax, 16 ; Xleft
.calculate_abs_coords:
mov edi, [TASK_BASE]
mov ebx, [edi-twdw + WDATA.box.left]
mov ecx, [edi-twdw + WDATA.box.top]
add ebx, eax
add ecx, edx
mov [img_screen_x], ebx ; abs Xleft
; mov [img_screen_y], ecx ; ecx = abs Ytop ; hold it !
.check_x_size:
mov ebx, [edi-twdw + WDATA.box.width]
inc ebx ; ebx = window Xsize
sub ebx, eax ; eax = rel Xleft
jbe .finish ; image is out of the window
mov eax, [putimg.image_sx]
cmp ebx, eax ; real_sx = MIN(wnd_sx-image_cx, image_sx);
jae @f
mov eax, ebx
@@: dec eax
mov [img_pix_x], eax
.check_y_size:
mov ebx, [edi-twdw + WDATA.box.height]
inc ebx ; ebx = real window y-size
sub ebx, edx ; edx = rel Ytop
jbe .finish ; image isn't visible
mov edx, [putimg.image_sy]
cmp ebx, edx
jae @f
mov edx, ebx
@@: mov [img_pix_y], edx
.calculate_lfb_origin:
mov edi, ecx ; ecx = absY
imul edi, [BytesPerScanLine]
mov eax, [img_screen_x] ; eax = absX
lea edi, [edi+eax*4]
add edi, LFB_BASE ; edi -> Screen origin
mov [img_lfb_origin], edi
.calculate_map_origin:
xor ebx, ebx
mov bl, byte [img_bytes_per_pix]
or bl, bl
jnz @f
mov ecx, [img_buf_line_size]
or cl, cl
je @f
bts ebx, 25
@@: mov bl, byte [CURRENT_TASK] ; get process number
mov ebp, ecx ; ecx = absY
shr ebp, 1 ; CF= odd line
jnc @f
bts ebx, 24 ; ebx[24] = odd start line
@@: imul ebp, [_WinMapWidth]
add ebp, [_WinMapAddress]
mov ecx, eax ; eax = absX
shr ecx, 2
add eax, [img_pix_x]
inc eax
shr eax, 2
add eax, ebp
; mov [img_map_right], eax ; right edge tile
add ebp, ecx ; left edge Map origin
mov ecx, [img_pix_y]
sub eax, ebp
jz .thin_bar ; special case: all image is 1 tile thick
mov [img_map_x], eax ; tiles in row (excluding the right one)
; ----- at this point:
; esi = [img_buf_origin] -> buffered image
; edi = [img_lfb_origin] -> LFB image (corner point, 0RGB format)
; ebp -> corner tile position
; ecx = [img_pix_y] = image height
; bl = task #
; ebx[24] = 1 if Ytop is odd
; ebx[25] = 1 if 1bpp image
.start:
bt ebx, 25
jnc @f
xor eax, eax
inc al
mov [img_bitoffset], eax ; 1bpp image must be byte-aligned
mov [img_edgeoffset], eax
@@:
mov edx, edi
mov dh, 0x0C
and dl, dh
jz .go_right ; left edge already aligned
.left_edge:
sub dh, dl
movzx edx, dh
call draw_unaligned_edge
dec [img_map_x]
shr edi, 4
inc edi ; align edi to the next 16-byte tile
shl edi, 4
mov [img_lfb_origin], edi ; core Screen origin
shr edx, 2
inc edx
sub [img_pix_x], edx ; shrink image width
bt ebx, 25
jnc @f
xchg dl, cl
mov eax, [img_edgeoffset] ; that's for 1bpp images only
shl eax, cl
mov [img_edgeoffset], eax
mov [img_bitoffset], eax
xchg dl, cl
@@: mov eax, edx
imul eax, [img_bytes_per_pix] ; 0 for 1bbp bitmaps
add esi, eax
mov [img_buf_origin], esi ; core Buffer origin
inc ebp ; core Map origin
.go_right:
mov eax, [img_map_x]
mov edx, eax
bt ebx, 25 ; 1bpp image ?
jc .shift_mono
shl eax, 2
imul eax, [img_bytes_per_pix]
jmp .get_right
.shift_mono:
shr eax, 1 ; 2 tiles = 1 byte Buffer offset
jnc .get_right
rol byte [img_edgeoffset], 4 ; odd number of tiles: shift 4bits
.get_right:
add esi, eax ; rightEdge Buffer origin
push ebp
add ebp, edx ; rightEdge Map origin
mov eax, [img_pix_x]
shl eax, 2 ; 1 pix = 4 bytes
add eax, edi ; rightEdge last pix (LFB addr)
shl edx, 4
add edi, edx ; rightEdge Screen origin
movzx edx, al
mov eax, [img_map_x]
and dl, 0x0C
cmp dl, 0x0C
je .core_block ; rightEdge is already tile-aligned
.right_edge:
call draw_unaligned_edge
.core_block:
or eax, eax ; empty central core?
jz .finish
mov ebp, [esp]
mov edi, [img_lfb_origin]
mov esi, [img_buf_origin]
call draw_aligned_box
.finish:
add esp, (putimg.stack_data + 4)
; call [_display.enable_mouse]
popad
ret
.thin_bar: ; < a special case > : one-tile-wide image
mov edx, [img_pix_x]
shl edx, 2 ; edx = rightmost tile offset (0, 4, 8, or 12 bytes)
call draw_unaligned_edge
add esp, putimg.stack_data
popad
ret
;align 64
;img_test_struct_32: ; 8 x 10
; dd 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x778899, 0x887766
; dd 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755
; dd 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755, 0xAA7744
; dd 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755, 0xAA7744, 0xBB7733
; dd 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755, 0xAA7744
; dd 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766, 0x997755
; dd 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799, 0x887766
; dd 0x001122, 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788, 0x777799
; dd 0x220000, 0x001122, 0x112233, 0x223344, 0x334455, 0x445566, 0x556677, 0x667788
; dd 0x441100, 0x220000, 0x001122, 0x112233, 0x223344, 0x334455, 0x445566, 0x556677
;align 64
;img_test_struct_24: ; 8 x 16
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
; dw 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211, 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB
; dw 0xBBAA, 0xAACC, 0xCCBB, 0xBBAA, 0xAACC, 0xCCBB, 0x1100, 0x0022, 0x2211, 0x1100, 0x0022, 0x2211
;align 64
;img_test_struct_8: ; 20 x 10
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
; db 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
;align 64
;img_test_struct_1: ; 16 x 10
; db 0x0F, 0xF0
; db 0x0F, 0xF0
; db 0x3C, 0xC3
; db 0x3C, 0xC3
; db 0xF0, 0x0F
; db 0xF0, 0x0F
; db 0x3C, 0xC3
; db 0x3C, 0xC3
; db 0x0F, 0xF0
; db 0x0F, 0xF0
;align 64
;img_test_palette: ; 6 colors
; dd 0x00BB2233, 0xAA4466, 0x995555, 0x00339966, 0x00884455, 0x00775566, 0x00664455, 0x00553344, 0x0
;**************************************************************************************
align 4
__sys_putpixel:
push edx
mov edx, [TASK_BASE]
add eax, [edx-twdw+WDATA.box.left]
add ebx, [edx-twdw+WDATA.box.top]
pop edx
_putpixel:
; eax = x coordinate
; ebx = y coordinate
; ecx = ?? RR GG BB ; 0x01000000 negation
; edi = 0x00000001 force
cmp [Screen_Max_X], eax
jb .exit0
cmp [Screen_Max_Y], ebx
jb .exit0
.check_forced:
test edi,1 ; force ?
jnz .checked
.not_forced:
push ebx eax
shr eax, 2
shr ebx, 1
imul ebx, [_WinMapWidth] ; win_map (X size)/2
add ebx, eax
mov al, byte [CURRENT_TASK]
mov ah, byte [_WinMapAddress+ebx]
cmp ah, al
pop eax ebx
jne .exit0
.checked:
push ebx
imul ebx, [BytesPerScanLine]
lea ebx, [ebx+eax*4]
bt ecx, 24
jnc .noneg
mov ecx, [LFB_BASE+ebx]
xor ecx, 0x00FFFFFF
.noneg:
mov [LFB_BASE+ebx], ecx
pop ebx
.exit0:
ret
;align 4
;_put_pixel: ; left for compatibility with Vesa20_putpixel32
;; eax = x
;; ebx = y
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
; lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier)
;; mov eax, [esp+32-8+4] ; eax = color
; mov [LFB_BASE+edi], ecx
; ret
; DRAWLINE
align 4
__sys_draw_line:
call [_display.disable_mouse]
; draw a line
; eax = HIWORD = x1
; LOWORD = x2
; ebx = HIWORD = y1
; LOWORD = y2
; ecx = color
; edi = force ?
pusha
dl_x1 equ esp+20
dl_y1 equ esp+16
dl_x2 equ esp+12
dl_y2 equ esp+8
dl_dx equ esp+4
dl_dy equ esp+0
xor edx, edx ; clear edx
xor esi, esi ; unpack arguments
xor ebp, ebp
mov si, ax ; esi = x2
mov bp, bx ; ebp = y2
shr eax, 16 ; eax = x1
shr ebx, 16 ; ebx = y1
push eax ; save x1
push ebx ; save y1
push esi ; save x2
push ebp ; save y2
; checking x-axis...
sub esi, eax ; esi = x2-x1
push esi ; save y2-y1
jl .x2lx1 ; is x2 less than x1 ?
jg .no_vline ; x1 > x2 ?
mov edx, ebp ; else (if x1=x2)
call vline
push edx ; necessary to rightly restore stack frame at .exit
jmp .exit
.x2lx1:
neg esi ; get esi absolute value
.no_vline:
; checking y-axis...
sub ebp, ebx ; ebp = y2-y1
push ebp ; save y2-y1
jl .y2ly1 ; is y2 less than y1 ?
jg .no_hline ; y1 > y2 ?
mov edx, [dl_x2] ; else (if y1=y2)
call hline
jmp .exit
.y2ly1:
neg ebp ; get ebp absolute value
.no_hline:
cmp ebp, esi
jle .x_rules ; |y2-y1| < |x2-x1| ?
cmp [dl_y2], ebx ; make sure y1 is at the begining
jge .no_reverse1
neg dword [dl_dx]
mov edx, [dl_x2]
mov [dl_x2], eax
mov [dl_x1], edx
mov edx, [dl_y2]
mov [dl_y2], ebx
mov [dl_y1], edx
.no_reverse1:
mov eax, [dl_dx]
cdq ; extend eax sing to edx
shl eax, 16 ; using 16bit fix-point maths
idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1)
mov edx, ebp ; edx = counter (number of pixels to draw)
mov ebp, 1 *65536 ; <<16 ; ebp = dy = 1.0
mov esi, eax ; esi = dx
jmp .y_rules
.x_rules:
cmp [dl_x2], eax ; make sure x1 is at the begining
jge .no_reverse2
neg dword [dl_dy]
mov edx, [dl_x2]
mov [dl_x2], eax
mov [dl_x1], edx
mov edx, [dl_y2]
mov [dl_y2], ebx
mov [dl_y1], edx
.no_reverse2:
xor edx, edx
mov eax, [dl_dy]
cdq ; extend eax sing to edx
shl eax, 16 ; using 16bit fix-point maths
idiv esi ; eax = ((y2-y1)*65536)/(x2-x1)
mov edx, esi ; edx = counter (number of pixels to draw)
mov esi, 1 *65536 ;<< 16 ; esi = dx = 1.0
mov ebp, eax ; ebp = dy
.y_rules:
mov eax, [dl_x1]
mov ebx, [dl_y1]
shl eax, 16
shl ebx, 16
align 4
.draw:
push eax ebx
shr eax, 16
shr ebx, 16
call _putpixel
pop ebx eax
add ebx, ebp ; y = y+dy
add eax, esi ; x = x+dx
dec edx
jnz .draw
; force last drawn pixel to be at (x2,y2)
mov eax, [dl_x2]
mov ebx, [dl_y2]
call _putpixel
.exit:
add esp, 6*4
popa
call [draw_pointer] ; mouse
ret
align 4
hline:
; ------------ draw a horizontal line -------------
; eax = x1
; edx = x2
; ebx = y
; ecx = color
; edi = force ?
cmp ebx, [Screen_Max_Y]
jge .out
pushad
bt ecx, 24 ; color inversion check
rcl edi,1 ; forced graphics check
mov ebp, ebx
shr ebp, 1
imul ebp, [_WinMapWidth] ; ebp = screen map base
add ebp, [_WinMapAddress]
cmp edx, eax ; to make sure x2 > x1
jge @f
xchg eax, edx
@@:
cmp eax, [Screen_Max_X]
jge .exit
mov esi, eax
shr esi, 4
add ebp, esi ; ebp -> win_map element
imul ebx, [BytesPerScanLine] ; ebx -> LFB pix_line
add ebx, LFB_BASE
cmp edx, [Screen_Max_X] ; last check
jb @f
mov edx, [Screen_Max_X]
@@: mov esi, ecx ; store color here
mov cl, byte [CURRENT_TASK] ;
mov ch, cl
mov [CURRENT_TASK+2], cx
mov [CURRENT_TASK+1], cl ; replicate byte to dword
.newsegment:
mov ecx, [ebp] ; check the line segment (16 pixels!)
xor ecx, [CURRENT_TASK]
; -- the line ---
jmp dword [hline.drawtable + edi*4] ; (C) Serge, 2010
align 4 ; internal loop
.invert_color:
mov esi, [ebx+eax*4]
xor esi, 0x00FFFFFF
align 4
.check_overlap:
or cl, cl
jz .putpixel
jmp .nextpixel
align 4
.invert_force:
mov esi, [ebx+eax*4]
xor esi, 0x00FFFFFF
align 4
.putpixel:
mov [ebx+eax*4], esi
align 4
.nextpixel:
inc eax
cmp eax, edx
ja .exit ; line drawn -- exit all loops
test al, 3
jz .newtile
.newpixel:
jmp dword [hline.drawtable + edi*4] ; the internal loop
.newtile:
inc ebp
test ebp, 3
jz .newsegment ; the external loop
shr ecx, 8
jmp dword [hline.drawtable + edi*4]
.exit:
mov eax, 0x0FF
and [CURRENT_TASK], eax
popad
.out:
ret
align 4
.drawtable:
dd .check_overlap ; general case
dd .invert_color
dd .putpixel ; force to draw it
dd .invert_force
align 4
vline:
; --------- draw a vertical line ------------
; eax = x
; ebx = y1
; edx = y2
; ecx = color
; edi = force ?
cmp eax, [Screen_Max_X]
jge .out
pushad
bt ecx, 24 ; color inversion check
rcl edi, 1 ; forced graphics check
cmp edx, ebx ; to make sure y2 > y1
jge @f
xchg ebx, edx
@@:
cmp ebx, [Screen_Max_Y]
jge .exit
mov ebp, ebx
shr ebp, 1
imul ebp, [_WinMapWidth]
add ebp, [_WinMapAddress]
mov esi, eax
shr esi, 1
shr esi, 1
add ebp, esi ; ebp = screen map at (x, y1)
push ebx
imul ebx, [BytesPerScanLine]
shl eax, 1
shl eax, 1
add eax, ebx
add eax, LFB_BASE
pop ebx ; restore ebx = y1
cmp edx, [Screen_Max_Y] ; the last check
jb .draw
mov edx, [Screen_Max_Y] ; to prevent off-screen drawing
.draw:
jmp dword [vline.drawtable + edi*4]
align 4
.invert_color:
mov ecx, [eax]
xor ecx, 0x00FFFFFF
align 4
.check_overlap:
movzx esi, byte [ebp]
cmp esi, [CURRENT_TASK]
je .putpixel
jmp .nextpixel
align 4
.invert_force:
mov ecx, [eax]
xor ecx, 0x00FFFFFF
align 4
.putpixel:
mov [eax], ecx
align 4
.nextpixel:
add eax, [BytesPerScanLine]
inc ebx
test bl, 1
jnz @f
add ebp, [_WinMapWidth]
@@:
cmp ebx, edx
ja .exit
jmp dword [vline.drawtable + edi*4]
.exit:
shr edi, 1
popad
.out:
ret
align 4
.drawtable:
dd .check_overlap ; general case
dd .invert_color
dd .putpixel ; force to draw it
dd .invert_force
;*************************************************
align 4
; eax xOrigin
; ebx yOrigin
; ecx xSize
; edx ySize
; edi color
_drawbar:
pushad
sub esp, putimg.stack_data
mov [img_bytes_per_pix], 0
mov [img_buf_line_size], 0
mov [img_draw_core_fn], draw_core_0bpp
mov [img_draw_edge_fn], draw_edge_0bpp
mov [putimg.image_sx], ecx
mov [putimg.image_sy], edx
mov edx, ebx
mov [img_palette], edi
mov esi, img_palette
mov [img_buf_origin], esi
jmp _putimage.calculate_abs_coords
; ret
draw_background:
pushad
pushfd
cld ; increment edi here!
mov ebp, [_WinMapAddress]
mov eax, 0x00337766 ; bgndcolor
mov bl, 1
mov edx, [Screen_Max_X]
shr edx, 1
mov edi, LFB_BASE
mov esi, [BytesPerScanLine]
.new_row:
xor ecx, ecx
.fill:
cmp byte [ebp+ecx], bl
jne .next
mov [edi+esi], eax ; fill all 8 pixels of this tile
stosd
mov [edi+esi], eax
stosd
mov [edi+esi], eax
stosd
mov [edi+esi], eax
stosd
.next: inc ecx
cmp ecx, [_WinMapWidth]
jb .fill
dec edx
jz .done
add ebp, ecx ; += [_WinMapWidth]
add edi, esi ; += [BytesPerScanLine]
jmp .new_row
.done:
popfd
popad
ret
drawbackground_stretch: ; left for future development
call drawbackground
ret
drawbackground_tiled: ; left for future development
call drawbackground
ret
uglobal
align 4
bgr_cur_line rd 1920 ; maximum width of screen
bgr_next_line rd 1920
endg
_init_background:
; mov edi, BgrAuxTable
; xor edx, edx
;.loop2:
; mov eax, edx
; shl eax, 8
; neg eax
; mov ecx, 0x200
;.loop1:
; mov byte [edi], ah
; inc edi
; add eax, edx
; loop .loop1
; add dl, 4
; jnz .loop2
mov byte [REDRAW_BACKGROUND], 1
; mov dword[BgrAuxTable], 0x00337766
ret
diff16 "GRAPH32 code end ",0,$
diff10 "GRAPH32 code size",get_pixel,$