forked from KolibriOS/kolibrios
542cb02cea
git-svn-id: svn://kolibrios.org@1859 a494cfbc-eb01-0410-851d-a64ba20cac60
1238 lines
31 KiB
PHP
1238 lines
31 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; 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
|
|
jz .new_tile
|
|
bts ebx, 26 ; ebx[26] = 1 if edi/esi already pushed
|
|
jc .seek_visible
|
|
push edi
|
|
push esi
|
|
jmp .seek_visible
|
|
.new_tile:
|
|
inc ecx ; visible - scan the open space
|
|
cmp ecx, eax
|
|
jz .end_of_line
|
|
cmp bl, byte[ebp+ecx] ; overlapped? draw the visible segment if so
|
|
je .new_tile
|
|
|
|
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
|
|
shr ecx, 2
|
|
imul ecx, [img_bytes_per_pix]
|
|
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 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
|
|
bt 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
|
|
btr ebx, 24
|
|
.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_32bpp:
|
|
push eax
|
|
.putpix:
|
|
mov eax, [esi+edx]
|
|
mov [edi+edx], eax
|
|
sub dl, 4
|
|
jae .putpix
|
|
.exit:
|
|
mov dl, 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
|
|
test dl, bh
|
|
jz .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
|
|
test dl, bh
|
|
jz .exit
|
|
add dl, 4
|
|
inc esi
|
|
jmp .putpix
|
|
.exit:
|
|
pop ebp esi eax
|
|
ret
|
|
align 4
|
|
draw_edge_1bpp:
|
|
push eax ecx ebx ebp
|
|
mov ebp, [img_palette]
|
|
mov ebx, [ebp+4] ; forecolor
|
|
mov ebp, [ebp] ; backcolor
|
|
mov ecx, [img_edgeoffset] ; cl = 1 << left_edge_pix_num
|
|
mov ebp, [esi]
|
|
xor dl, dl
|
|
.testbit:
|
|
test ebp, ecx
|
|
jnz @f
|
|
mov eax, ebp
|
|
jmp .putpix
|
|
@@: mov eax, ebx
|
|
.putpix:
|
|
mov [edi+edx], eax
|
|
test dl, bh
|
|
jz .exit
|
|
add dl, 4
|
|
shl ecx, 1
|
|
jmp .testbit
|
|
.exit:
|
|
pop ebp ebx ecx eax
|
|
ret
|
|
|
|
draw_edge_16bpp:
|
|
draw_core_16bpp:
|
|
ret
|
|
|
|
;-------------
|
|
; aligned core helpers
|
|
; esi -> left point address (image)
|
|
; edi -> left point address (screen)
|
|
; cx = number of tiles to draw
|
|
align 4
|
|
draw_core_32bpp:
|
|
push ecx
|
|
shl ecx, 1
|
|
dec ecx
|
|
.putpix:
|
|
fld qword[esi+ecx*8] ; 2 qwords = 1 tile
|
|
fstp qword[edi+ecx*8]
|
|
dec cx
|
|
jnb .putpix
|
|
pop ecx
|
|
ret
|
|
align 4
|
|
draw_core_24bpp:
|
|
push eax ecx
|
|
shl ecx, 2
|
|
dec ecx
|
|
lea eax, [ecx*2+ecx]
|
|
.putpix:
|
|
mov eax, [esi+eax]
|
|
and eax, 0x00FFFFFF
|
|
mov [edi+ecx*4], eax
|
|
sub dx, 3
|
|
dec cx
|
|
jnb .putpix
|
|
pop 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 cx
|
|
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
|
|
dec ecx
|
|
jb .exit
|
|
.newblock:
|
|
mov eax, [esi]
|
|
.putpix:
|
|
test ebx, eax
|
|
jz .bkcolor
|
|
mov [edi], edx
|
|
jmp .nextpix
|
|
.bkcolor:
|
|
mov [edi], ebp
|
|
.nextpix:
|
|
dec cx
|
|
jb .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]
|
|
|
|
_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 ebx, [TASK_BASE-twdw + WDATA.box.left]
|
|
mov ecx, [TASK_BASE-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, [TASK_BASE-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, [TASK_BASE-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
|
|
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]
|
|
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 the core Y is odd
|
|
; ebx[25] = 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
|
|
and edx, 0x0C
|
|
jz .go_right ; left edge already aligned
|
|
.left_edge:
|
|
mov dh, 0x0C
|
|
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)
|
|
movzx edx, al
|
|
and dl, 0x0C
|
|
jz .core_block ; rightEdge is already tile-aligned
|
|
and al, 0xF0
|
|
mov edi, eax ; rightEdge Screen origin
|
|
.right_edge:
|
|
call draw_unaligned_edge
|
|
dec [img_map_x]
|
|
.core_block:
|
|
pop ebp
|
|
mov eax, [img_map_x]
|
|
or eax, eax ; empty central core?
|
|
jz .finish
|
|
mov edi, [img_lfb_origin]
|
|
mov esi, [img_buf_origin]
|
|
|
|
call draw_aligned_box
|
|
|
|
.finish:
|
|
add esp, putimg.stack_data
|
|
; 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
|
|
jmp .finish
|
|
|
|
|
|
align 64
|
|
img_test_struct:
|
|
dd 0x00112233, 0x00223344, 0x00334455, 0x00445566
|
|
dd 0x00223344, 0x00334455, 0x00445566, 0x00334455
|
|
dd 0x00334455, 0x00445566, 0x00334455, 0x00223344
|
|
dd 0x00445566, 0x00334455, 0x00223344, 0x00112233
|
|
|
|
;**************************************************************************************
|
|
align 4
|
|
__sys_putpixel:
|
|
_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, 1
|
|
shr eax, 1
|
|
shr ebx, 1
|
|
imul ebx, [_WinMapWidth] ; win_map (X size)/2
|
|
add ebx, eax
|
|
mov al, byte [CURRENT_TASK]
|
|
mov bl, byte [_WinMapAddress+ebx]
|
|
cmp bl, 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] ; a coolhack (C) Serge
|
|
|
|
|
|
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
|
|
|
|
|
|
;*************************************************
|
|
|
|
|
|
virtual at esp
|
|
drbar:
|
|
.bar_sx dd ?
|
|
.bar_sy dd ?
|
|
.bar_cx dd ?
|
|
.bar_cy dd ?
|
|
.abs_cx dd ?
|
|
.abs_cy dd ?
|
|
.real_sx dd ?
|
|
.real_sy dd ?
|
|
.color dd ?
|
|
.line_inc_scr dd ?
|
|
.line_inc_map dd ?
|
|
.stack_data = 4*11
|
|
end virtual
|
|
|
|
align 4
|
|
; eax cx
|
|
; ebx cy
|
|
; ecx xe
|
|
; edx ye
|
|
; edi color
|
|
vesa20_drawbar:
|
|
pushad
|
|
call [_display.disable_mouse]
|
|
sub esp, drbar.stack_data
|
|
mov [drbar.color], edi
|
|
sub edx, ebx
|
|
jle .exit
|
|
sub ecx, eax
|
|
jle .exit
|
|
mov [drbar.bar_sy], edx
|
|
mov [drbar.bar_sx], ecx
|
|
mov [drbar.bar_cx], eax
|
|
mov [drbar.bar_cy], ebx
|
|
mov edi, [TASK_BASE]
|
|
add eax, [edi-twdw + WDATA.box.left] ; win_cx
|
|
add ebx, [edi-twdw + WDATA.box.top] ; win_cy
|
|
mov [drbar.abs_cx], eax
|
|
mov [drbar.abs_cy], ebx
|
|
; real_sx = MIN(wnd_sx-bar_cx, bar_sx);
|
|
mov ebx, [edi-twdw + WDATA.box.width] ; ebx = wnd_sx
|
|
; note that WDATA.box.width is one pixel less than real window x-size
|
|
inc ebx
|
|
sub ebx, [drbar.bar_cx]
|
|
ja @f
|
|
.exit:
|
|
add esp, drbar.stack_data
|
|
popad
|
|
xor eax, eax
|
|
inc eax
|
|
ret
|
|
@@:
|
|
cmp ebx, [drbar.bar_sx]
|
|
jbe .end_x
|
|
mov ebx, [drbar.bar_sx]
|
|
.end_x:
|
|
mov [drbar.real_sx], ebx
|
|
; real_sy = MIN(wnd_sy-bar_cy, bar_sy);
|
|
mov ebx, [edi-twdw + WDATA.box.height] ; ebx = wnd_sy
|
|
inc ebx
|
|
sub ebx, [drbar.bar_cy]
|
|
ja @f
|
|
add esp, drbar.stack_data
|
|
popad
|
|
xor eax, eax
|
|
inc eax
|
|
ret
|
|
@@:
|
|
cmp ebx, [drbar.bar_sy]
|
|
jbe .end_y
|
|
mov ebx, [drbar.bar_sy]
|
|
.end_y:
|
|
mov [drbar.real_sy], ebx
|
|
; line_inc_map
|
|
mov eax, [Screen_Max_X]
|
|
sub eax, [drbar.real_sx]
|
|
inc eax
|
|
shr eax, 1 ; <<<<<<
|
|
shr eax, 1
|
|
mov [drbar.line_inc_map], eax ; vertical increment: map
|
|
; line_inc_scr
|
|
mov eax, [drbar.real_sx]
|
|
shl eax, 1
|
|
shl eax, 1
|
|
neg eax
|
|
add eax, [BytesPerScanLine]
|
|
mov [drbar.line_inc_scr], eax ; vertical increment: screen
|
|
; pointer to screen
|
|
mov edx, [drbar.abs_cy]
|
|
mov ebx, edx
|
|
imul edx, [BytesPerScanLine] ; edx = LFB line offset
|
|
mov eax, [drbar.abs_cx]
|
|
shl eax, 1
|
|
shl eax, 1
|
|
add edx, eax ; edx = LFB corner offset
|
|
; pointer to pixel map
|
|
shr ebx, 1
|
|
imul ebx, [_WinMapWidth] ; eax = Wmap corner pos
|
|
mov eax, [drbar.abs_cx]
|
|
shr eax, 1
|
|
shr eax, 1
|
|
add eax, ebx
|
|
add eax, [_WinMapAddress]
|
|
xchg eax, ebp ; ebp = Wmap corner
|
|
; get process number
|
|
mov ebx, [CURRENT_TASK]
|
|
|
|
; eax - RGB-color
|
|
; bl - process num
|
|
; ecx - pix counter (in a tile)
|
|
; edx - pointer to screen
|
|
; esi - counter
|
|
; edi - counter
|
|
|
|
mov eax, [drbar.color] ;; BBGGRR00
|
|
mov esi, 0
|
|
align 4
|
|
.new_y:
|
|
mov edi, [drbar.real_sx]
|
|
movzx ecx, dl
|
|
shr cl, 2 ; pix# = edx/4
|
|
and cl, 3 ; pix position in a tile
|
|
.new_tile:
|
|
cmp byte [ebp], bl
|
|
jne .skip
|
|
.new_x:
|
|
mov [LFB_BASE+edx], eax
|
|
add edx, 4
|
|
dec edi
|
|
jz .add_line
|
|
inc cl
|
|
and cl, 3
|
|
jnz .new_x
|
|
jmp .new_tile
|
|
.skip:
|
|
add edx, 4*4
|
|
and dl, 0xF0 ; LFB align 16
|
|
inc ebp
|
|
sub edi, 4 ; <<<<<
|
|
add edi, ecx ; left tile may be 1,2 or 3px only
|
|
jae .new_tile
|
|
|
|
.add_line:
|
|
add edx, [drbar.line_inc_scr]
|
|
; gradient-filled bars
|
|
test eax, 0x80000000
|
|
jz @f
|
|
test al, al
|
|
jz @f
|
|
dec al
|
|
@@:
|
|
inc esi
|
|
test esi, 1
|
|
jne @f
|
|
add ebp, [drbar.line_inc_map]
|
|
@@:
|
|
cmp esi, [drbar.real_sy]
|
|
jbe .new_y
|
|
add esp, drbar.stack_data
|
|
popad
|
|
xor eax, eax
|
|
ret
|
|
|
|
|
|
align 4
|
|
;drawbackground:
|
|
call [_display.disable_mouse]
|
|
pushad
|
|
; External loop for all y from start to end
|
|
mov ebx, [draw_data+32+RECT.top] ; y start
|
|
.fill_line:
|
|
mov edi, [draw_data+32+RECT.left] ; x start
|
|
shl edi, 1
|
|
shl edi, 1
|
|
mov eax, [BytesPerScanLine]
|
|
mul ebx
|
|
xchg edi, eax
|
|
add edi, eax
|
|
add edi, LFB_BASE
|
|
|
|
mov ebp, ebx
|
|
shr ebp, 1
|
|
imul ebp, [_WinMapWidth]
|
|
mov edx, eax
|
|
shr edx, 1
|
|
shr edx, 1
|
|
add ebp, edx
|
|
add ebp, [_WinMapAddress]
|
|
xor edx, edx
|
|
inc edx
|
|
mov esi, 0x0336677 ; <<< RGB
|
|
; eax = x, ebx = y (screen coordinates)
|
|
; ecx - aux. var
|
|
; edx = 1
|
|
; esi = 0RGB, edi -> output
|
|
; ebp = offset in WinMapAddress
|
|
.fill_tile:
|
|
cmp [ebp], dl
|
|
jnz .next_tile
|
|
mov [edi], esi
|
|
mov [edi+4], esi
|
|
mov [edi+8], esi
|
|
mov [edi+12],esi
|
|
mov ecx, [BytesPerScanLine]
|
|
mov [ecx+edi], esi
|
|
mov [ecx+edi+4], esi
|
|
mov [ecx+edi+8], esi
|
|
mov [ecx+edi+12],esi
|
|
.next_tile:
|
|
add edi, 4*4
|
|
add ebp, edx
|
|
add ax, 4
|
|
mov ecx, [draw_data+32+RECT.right]
|
|
shr ecx, 1
|
|
shr ecx, 1
|
|
cmp eax, ecx
|
|
jbe .fill_tile
|
|
|
|
.next_line:
|
|
inc ebx
|
|
mov ecx, [draw_data+32+RECT.bottom]
|
|
shr ecx, 1
|
|
jbe .fill_line
|
|
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
|
|
|
|
smooth_line:
|
|
mov al, [esi+2]
|
|
shl eax, 16
|
|
mov ax, [esi]
|
|
test ecx, ecx
|
|
jz @f
|
|
mov ebx, [esi+2]
|
|
shr ebx, 8
|
|
call [overlapping_of_points_ptr]
|
|
@@:
|
|
stosd
|
|
mov eax, [esp+20+8]
|
|
inc eax
|
|
mov [esp+20+8], eax
|
|
cmp eax, [draw_data+32+RECT.right]
|
|
ja @f
|
|
add ecx, [esp+36+8]
|
|
mov eax, edx
|
|
adc edx, [esp+40+8]
|
|
sub eax, edx
|
|
lea eax, [eax*3]
|
|
sub esi, eax
|
|
jmp smooth_line
|
|
@@:
|
|
mov eax, [draw_data+32+RECT.left]
|
|
mov [esp+20+8], eax
|
|
ret
|
|
|
|
align 16
|
|
overlapping_of_points:
|
|
push ecx edx
|
|
mov edx, eax
|
|
push esi
|
|
shr ecx, 26
|
|
mov esi, ecx
|
|
mov ecx, ebx
|
|
shl esi, 9
|
|
movzx ebx, dl
|
|
movzx eax, cl
|
|
sub eax, ebx
|
|
movzx ebx, dh
|
|
add dl, [BgrAuxTable+(eax+0x100)+esi]
|
|
movzx eax, ch
|
|
sub eax, ebx
|
|
add dh, [BgrAuxTable+(eax+0x100)+esi]
|
|
ror ecx, 16
|
|
ror edx, 16
|
|
movzx eax, cl
|
|
movzx ebx, dl
|
|
sub eax, ebx
|
|
add dl, [BgrAuxTable+(eax+0x100)+esi]
|
|
pop esi
|
|
mov eax, edx
|
|
pop edx
|
|
ror eax, 16
|
|
pop ecx
|
|
ret
|
|
|
|
iglobal
|
|
align 4
|
|
overlapping_of_points_ptr dd overlapping_of_points
|
|
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
|
|
test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8)
|
|
jz @f
|
|
mov [overlapping_of_points_ptr], overlapping_of_points_mmx
|
|
@@:
|
|
ret
|
|
|
|
align 16
|
|
overlapping_of_points_mmx:
|
|
movd mm0, eax
|
|
movd mm4, eax
|
|
movd mm1, ebx
|
|
pxor mm2, mm2
|
|
punpcklbw mm0, mm2
|
|
punpcklbw mm1, mm2
|
|
psubw mm1, mm0
|
|
movd mm3, ecx
|
|
psrld mm3, 24
|
|
packuswb mm3, mm3
|
|
packuswb mm3, mm3
|
|
pmullw mm1, mm3
|
|
psrlw mm1, 8
|
|
packuswb mm1, mm2
|
|
paddb mm4, mm1
|
|
movd eax, mm4
|
|
ret
|
|
diff16 "GRAPH32 code end ",0,$
|
|
diff10 "GRAPH32 code size",get_pixel,$
|
|
|
|
|