kolibrios-fun/kernel/branches/Kolibri-A/trunk/video/graph32.inc
Artem Jerdev (art_zh) 542cb02cea new "tiled" graph engine (* buggy version *)
git-svn-id: svn://kolibrios.org@1859 a494cfbc-eb01-0410-851d-a64ba20cac60
2011-02-09 14:48:45 +00:00

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,$