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