0,0 → 1,1064 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; VESA20.INC ;; |
;; ;; |
;; Vesa 2.0 functions for MenuetOS ;; |
;; ;; |
;; Copyright 2002 Ville Turjanmaa ;; |
;; Alexey, kgaz@crosswindws.net ;; |
;; - Voodoo compatible graphics ;; |
;; Juan M. Caravaca ;; |
;; - Graphics optimimizations eg. drawline ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
$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 |
|
;************************************************* |
|
virtual at esp |
putimg: |
.real_sx dd ? |
.real_sy dd ? |
.image_sx dd ? |
.image_sy dd ? |
.image_cx dd ? |
.image_cy dd ? |
.pti dd ? |
.abs_cx dd ? |
.abs_cy dd ? |
.line_increment dd ? |
.winmap_newline dd ? |
.screen_newline dd ? |
.stack_data = 4*12 |
.edi dd ? |
.esi dd ? |
.ebp dd ? |
.esp dd ? |
.ebx dd ? |
.edx dd ? |
.ecx dd ? |
.eax dd ? |
.ret_addr dd ? |
.arg_0 dd ? |
end virtual |
|
align 16 |
; ebx = pointer |
; ecx = size [x|y] |
; edx = coordinates [x|y] |
; ebp = pointer to 'get' function |
; esi = pointer to 'init' function |
; edi = parameter for 'get' function |
|
vesa20_putimage: |
pushad |
call [_display.disable_mouse] |
sub esp, putimg.stack_data |
; save pointer to image |
mov [putimg.pti], ebx |
; unpack the size |
mov eax, ecx |
and ecx, 0xFFFF |
shr eax, 16 |
mov [putimg.image_sx], eax |
mov [putimg.image_sy], ecx |
; unpack the coordinates |
mov eax, edx |
and edx, 0xFFFF |
shr eax, 16 |
mov [putimg.image_cx], eax |
mov [putimg.image_cy], edx |
; calculate absolute (i.e. screen) coordinates |
mov eax, [TASK_BASE] |
mov ebx, [eax-twdw + WDATA.box.left] |
add ebx, [putimg.image_cx] |
mov [putimg.abs_cx], ebx |
mov ebx, [eax-twdw + WDATA.box.top] |
add ebx, [putimg.image_cy] |
mov [putimg.abs_cy], ebx |
; real_sx = MIN(wnd_sx-image_cx, image_sx); |
mov ebx, [eax-twdw + WDATA.box.width] ; ebx = wnd_sx |
inc ebx ; WDATA.box.width is one pixel less than real window x-size |
sub ebx, [putimg.image_cx] |
ja @f |
add esp, putimg.stack_data |
popad |
ret |
@@: |
cmp ebx, [putimg.image_sx] |
jbe .end_x |
mov ebx, [putimg.image_sx] |
.end_x: |
mov [putimg.real_sx], ebx |
; init real_sy |
mov ebx, [eax-twdw + WDATA.box.height] ; ebx = wnd_sy |
inc ebx |
sub ebx, [putimg.image_cy] |
ja @f |
add esp, putimg.stack_data |
popad |
ret |
@@: |
cmp ebx, [putimg.image_sy] |
jbe .end_y |
mov ebx, [putimg.image_sy] |
.end_y: |
mov [putimg.real_sy], ebx |
; line increment |
mov eax, [putimg.image_sx] |
mov ecx, [putimg.real_sx] |
sub eax, ecx |
call esi |
add eax, [putimg.arg_0] |
mov [putimg.line_increment], eax |
; winmap new line increment |
mov eax, [Screen_Max_X] |
inc eax |
sub eax, [putimg.real_sx] |
mov [putimg.winmap_newline], eax |
; screen new line increment |
mov eax, [BytesPerScanLine] |
shl ecx, 1 |
shl ecx, 1 |
sub eax, ecx |
mov [putimg.screen_newline], eax |
; pointer to image |
mov esi, [putimg.pti] |
; pointer to screen |
mov edx, [putimg.abs_cy] |
imul edx, [BytesPerScanLine] |
mov eax, [putimg.abs_cx] |
shl eax, 1 |
shl eax, 1 |
add edx, eax |
; pointer to pixel map |
mov eax, [putimg.abs_cy] |
imul eax, [Screen_Max_X] |
add eax, [putimg.abs_cy] |
add eax, [putimg.abs_cx] |
add eax, [_WinMapAddress] |
xchg eax, ebp |
; get process number |
mov ebx, [CURRENT_TASK] |
|
put_image_end_32: |
mov edi, [putimg.real_sy] |
align 4 |
.new_line: |
mov ecx, [putimg.real_sx] |
align 4 |
.new_x: |
push [putimg.edi] |
mov eax, [putimg.ebp+4] |
call eax |
cmp [ebp], bl |
jne .skip |
mov [LFB_BASE+edx], eax |
.skip: |
add edx, 4 |
inc ebp |
dec ecx |
jnz .new_x |
add esi, [putimg.line_increment] |
add edx, [putimg.screen_newline] ;[BytesPerScanLine] |
add ebp, [putimg.winmap_newline] ;[Screen_Max_X] |
cmp [putimg.ebp], putimage_get1bpp |
jz .correct |
cmp [putimg.ebp], putimage_get2bpp |
jz .correct |
cmp [putimg.ebp], putimage_get4bpp |
jnz @f |
.correct: |
mov eax, [putimg.edi] |
mov byte [eax], 80h |
@@: |
dec edi |
jnz .new_line |
.finish: |
add esp, putimg.stack_data |
popad |
ret |
|
;************************************************* |
align 4 |
__sys_putpixel: |
|
; eax = x coordinate |
; ebx = y coordinate |
; ecx = ?? RR GG BB ; 0x01000000 negation |
; edi = 0x00000001 force |
|
cmp [Screen_Max_X], eax |
jb .exit |
cmp [Screen_Max_Y], ebx |
jb .exit |
.check_forced: |
test edi,1 ; force ? |
jnz .checked |
|
.not_forced: |
push edx |
mov edx,[_display.width] ; screen x size |
imul edx, ebx |
add edx, [_WinMapAddress] |
movzx edx, byte [eax+edx] |
cmp edx, [CURRENT_TASK] |
pop edx |
jne .exit |
|
; OK to set pixel |
.checked: |
push ebx |
imul ebx, [BytesPerScanLine] |
lea ebx, [ebx+eax*4] |
test ecx,0x01000000 |
jz .noneg |
mov ecx, [LFB_BASE+ebx] |
not ecx |
and ecx, 0x01FFFFFF |
.noneg: |
mov [LFB_BASE+ebx], ecx |
pop ebx |
.exit: |
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 |
|
|
;************************************************* |
|
;align 4 |
calculate_edi: |
mov edi, ebx |
imul edi, [Screen_Max_X] |
add edi, ebx |
add edi, eax |
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] |
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 |
push eax ebp esi ebx edx |
bt ecx, 24 ; color inversion check |
rcl edi,1 ; forced graphics check |
|
mov ebp, [_display.width] ; ebp = screen co-ords base |
imul ebp, ebx |
add ebp, [_WinMapAddress] |
|
cmp edx, eax ; to make sure x2 > x1 |
jge @f |
xchg eax, edx |
@@: |
cmp eax, [Screen_Max_X] |
jge .exit |
imul ebx, [BytesPerScanLine] |
add ebx, LFB_BASE |
cmp edx, [Screen_Max_X] ; last check |
jb .draw |
mov edx, [Screen_Max_X] |
|
.draw: ; -- the line --- |
jmp dword [hline.drawtable + edi*4] ; a coolhack (C) Serge |
|
align 4 |
.invert_color: |
mov ecx, [ebx+eax*4] |
xor ecx, 0x00FFFFFF |
or ecx, 0x01000000 ; keep bit[24] high ! |
align 4 |
.check_overlap: |
movzx esi, byte [ebp+eax] ; check whether the line covered by other windows |
cmp esi, [CURRENT_TASK] |
je .putpixel |
jmp .nextpixel |
align 4 |
.invert_force: |
mov ecx, [ebx+eax*4] |
xor ecx, 0x00FFFFFF |
or ecx, 0x01000000 ; keep bit[24] high ! |
align 4 |
.putpixel: |
mov [ebx+eax*4], ecx |
align 4 |
.nextpixel: |
inc eax |
cmp eax, edx |
ja .exit |
jmp dword [hline.drawtable + edi*4] ; close the loop |
|
.exit: |
shr edi, 1 ; restore the 'force' bit |
pop edx ebx esi ebp eax |
.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 |
push eax ebp esi ebx edx |
mov ebp, [_display.width] ; ebp = screen co-ords base |
imul ebp, ebx |
add ebp, [_WinMapAddress] |
add ebp, eax |
|
cmp edx, ebx ; to make sure y2 > y1 |
jge @f |
xchg ebx, edx |
@@: |
cmp ebx, [Screen_Max_Y] |
jge .exit |
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 |
or ecx, 0x01000000 |
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 |
or ecx, 0x01000000 |
align 4 |
.putpixel: |
mov [eax], ecx |
align 4 |
.nextpixel: |
add eax, [BytesPerScanLine] |
add ebp, [_display.width] |
inc ebx |
cmp ebx, edx |
ja .exit |
jmp dword [vline.drawtable + edi*4] |
.exit: |
shr edi, 1 |
pop edx ebx esi ebp eax |
.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 |
mov [drbar.line_inc_map], eax |
; 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 |
; pointer to screen |
mov edx, [drbar.abs_cy] |
imul edx, [BytesPerScanLine] |
mov eax, [drbar.abs_cx] |
shl eax, 1 |
shl eax, 1 |
add edx, eax |
; pointer to pixel map |
mov eax, [drbar.abs_cy] |
|