flat assembler
Message board for the users of flat assembler.
Index
> Linux > Fastest and very "assembly" way to draw in Linux. Goto page Previous 1, 2, 3 Next |
Author |
|
revolution 24 Dec 2018, 13:24
Hmm, I'm not sure either:
Code: ~ sudo apt-get install libxft2 [sudo] password for revolution: Reading package lists... Done Building dependency tree Reading state information... Done libxft2 is already the newest version (2.3.2-1). |
|||
24 Dec 2018, 13:24 |
|
revolution 24 Dec 2018, 14:09
This works:
Code: sudo apt-get install libxft2:i386 |
|||
24 Dec 2018, 14:09 |
|
revolution 24 Dec 2018, 15:21
It should probably be noted that this is for the X11 server. Most Linux distros that incorporate a GUI use X11. But for those distros that don't have X11, or don't have a GUI, then something else (like using the frame buffer) will be needed.
|
|||
24 Dec 2018, 15:21 |
|
revolution 25 Dec 2018, 09:31
For an even lower level of drawing in Linux, here is some simple code to draw directly to the frame buffer:
Code: format ELF executable 3 entry main FRAME_BUFER_NAME equ '/dev/fb0' TEST_COLOUR = 0x00ffff00 ; Yellow TEST_DELAY = 2000 ; 2 seconds SYS_EXIT = 1 SYS_WRITE = 4 SYS_OPEN = 5 SYS_CLOSE = 6 SYS_IOCTL = 54 SYS_MUNMAP = 91 SYS_NANOSLEEP = 162 SYS_MMAP_PGOFF = 192 NULL = 0 HANDLE_STD_OUTPUT = 1 MAXIMUM_ERROR_NUMBER = -256 INVALID_HANDLE_VALUE = -1 O_RDWR = 2 FBIOGET_VSCREENINFO = 0x4600 FBIOGET_FSCREENINFO = 0x4602 PROT_READ = 1 ;Page can be read PROT_WRITE = 2 ;Page can be written MAP_SHARED = 1 ;Share changes struc fb_fix_screeninfo { .id rb 16 ; identification string eg "TT Builtin" .smem_start rd 1 ; Start of frame buffer mem (physical address) .smem_len rd 1 ; Length of frame buffer mem .type rd 1 ; see FB_TYPE_* .type_aux rd 1 ; Interleave for interleaved Planes .visual rd 1 ; see FB_VISUAL_* .xpanstep rw 1 ; zero if no hardware panning .ypanstep rw 1 ; zero if no hardware panning .ywrapstep rw 1 ; zero if no hardware ywrap .align_0 rw 1 .line_length rd 1 ; length of a line in bytes .mmio_start rd 1 ; Start of Memory Mapped I/O (physical address) .mmio_len rd 1 ; Length of Memory Mapped I/O .accel rd 1 ; Indicate to driver which specific chip/card we have .capabilities rw 1 ; see FB_CAP_* .reserved rw 2 ; Reserved for future compatibility .align_1 rw 1 } struc fb_bitfield { .offset rd 1 ; beginning of bitfield .length rd 1 ; length of bitfield .msb_right rd 1 ; != 0 : Most significant bit is right } struc fb_var_screeninfo { .xres rd 1 ; visible resolution .yres rd 1 .xres_virtual rd 1 ; virtual resolution .yres_virtual rd 1 .xoffset rd 1 ; offset from virtual to visible .yoffset rd 1 ; resolution .bits_per_pixel rd 1 ; guess what .grayscale rd 1 ; 0 = color, 1 = grayscale, >1 = FOURCC .red fb_bitfield ; bitfield in fb mem if true color, .green fb_bitfield ; else only length is significant .blue fb_bitfield .transp fb_bitfield ; transparency .nonstd rd 1 ; != 0 Non standard pixel format .activate rd 1 ; see FB_ACTIVATE_* .height rd 1 ; height of picture in mm .width rd 1 ; width of picture in mm .accel_flags rd 1 ; (OBSOLETE) see fb_info.flags .pixclock rd 1 ; pixel clock in ps (pico seconds) .left_margin rd 1 ; time from sync to picture .right_margin rd 1 ; time from picture to sync .upper_margin rd 1 ; time from sync to picture .lower_margin rd 1 .hsync_len rd 1 ; length of horizontal sync .vsync_len rd 1 ; length of vertical sync .sync rd 1 ; see FB_SYNC_* .vmode rd 1 ; see FB_VMODE_* .rotate rd 1 ; angle we rotate counter clockwise .colorspace rd 1 ; colorspace for FOURCC-based modes .reserved rd 4 ; Reserved for future compatibility } segment readable writeable handle_fb dd INVALID_HANDLE_VALUE handle_fb_map dd INVALID_HANDLE_VALUE handle_fb_map.len dd ? fixed_screeninfo fb_fix_screeninfo variable_screeninfo fb_var_screeninfo segment readable frame_buffer_name: db FRAME_BUFER_NAME,0 success_opening_fb: db 'Open ',FRAME_BUFER_NAME,' okay (%)',10,0 success_reading_fixed_info: db 'Read fb_fix_screeninfo okay',10,0 success_reading_variable_info: db 'Read fb_var_screeninfo okay',10,0 show_fixed_info: db 'frame buff %',10 db 'frame len %',10 db 'mem start %',10 db 'mem len %',10 db 'line length %',10,0 show_variable_info: db 'x visible %',10 db 'y visible %',10 db 'x virtual %',10 db 'y virtual %',10 db 'x offset %',10 db 'y offset %',10 db 'pixel bits %',10,0 clean_exit: db 'Everything is okay',10,0 error_opening_fb: db 'Cannot open ',FRAME_BUFER_NAME,10,0 error_opening_fb.exit = 1 error_reading_fixed_info: db 'Cannot read fb_fix_screeninfo',10,0 error_reading_fixed_info.exit = 2 error_reading_variable_info: db 'Cannot read fb_var_screeninfo',10,0 error_reading_variable_info.exit = 3 error_allocating_fb_map: db 'Cannot allocate memory map for the frame buffer',10,0 error_allocating_fb_map.exit = 4 segment executable macro sys p1,p2,p3,p4,p5,p6,p7 { macro def reg,param \{ if ~ param eq & ~ reg eq param if param eqtype 0 & param = 0 xor reg,reg else mov reg,param end if end if \} def ebp,p7 def edi,p6 def esi,p5 def edx,p4 def ecx,p3 def ebx,p2 def eax,p1 int 0x80 purge def } macro printf string,[parameter] { common local parameter_count parameter_count = 0 reverse if ~ parameter eq parameter_count = parameter_count + 1 push parameter end if common mov eax,string call simple_printf if parameter_count > 0 add esp,parameter_count * 4 end if } main: sys SYS_OPEN,frame_buffer_name,O_RDWR,0 cmp eax,MAXIMUM_ERROR_NUMBER ja .error_opening_fb mov [handle_fb],eax printf success_opening_fb,eax sys SYS_IOCTL,[handle_fb],FBIOGET_FSCREENINFO,fixed_screeninfo test eax,eax jnz .error_reading_fixed_info printf success_reading_fixed_info sys SYS_IOCTL,[handle_fb],FBIOGET_VSCREENINFO,variable_screeninfo test eax,eax jnz .error_reading_variable_info printf success_reading_variable_info ;show some information that was discovered printf show_fixed_info,[fixed_screeninfo.smem_start],[fixed_screeninfo.smem_len],[fixed_screeninfo.mmio_start],[fixed_screeninfo.mmio_len],[fixed_screeninfo.line_length] printf show_variable_info,[variable_screeninfo.xres],[variable_screeninfo.yres],[variable_screeninfo.xres_virtual],[variable_screeninfo.yres_virtual],[variable_screeninfo.xoffset],[variable_screeninfo.yoffset],[variable_screeninfo.bits_per_pixel] ;setup a place in memory to access the frame buffer mov eax,[variable_screeninfo.yres_virtual] mul [fixed_screeninfo.line_length] mov [handle_fb_map.len],eax sys SYS_MMAP_PGOFF,0,eax,PROT_READ or PROT_WRITE,MAP_SHARED,[handle_fb],0 cmp eax,MAXIMUM_ERROR_NUMBER ja .error_allocating_fb_map mov [handle_fb_map],eax ;draw a simple test mov edi,[handle_fb_map] mov eax,TEST_COLOUR mov ecx,[handle_fb_map.len] shr ecx,2 cld rep stosd ;show this awesome test screen for a short period mov eax,TEST_DELAY call sleep_milliseconds ;everything worked printf clean_exit mov eax,NULL jmp exit .error_opening_fb: printf error_opening_fb mov eax,error_opening_fb.exit jmp exit .error_reading_fixed_info: printf error_reading_fixed_info mov eax,error_reading_fixed_info.exit jmp exit .error_reading_variable_info: printf error_reading_variable_info mov eax,error_reading_variable_info.exit jmp exit .error_allocating_fb_map: printf error_allocating_fb_map mov eax,error_allocating_fb_map.exit jmp exit simple_printf: ;eax = string ;stack = parameters ;supports only % to expand to an unsigned decimal number mov edi,esp mov esi,eax cld .next_char: lodsb test al,al jz .done cmp al,'%' jnz .print_char add edi,4 mov eax,[edi] mov ecx,10 push -1 .next_digit: xor edx,edx div ecx push edx test eax,eax jnz .next_digit .print_digits: pop eax test eax,eax js .next_char add al,'0' call simple_print_char jmp .print_digits .print_char: call simple_print_char jmp .next_char .done: ret simple_print_char: ;al = char push eax sys SYS_WRITE,HANDLE_STD_OUTPUT,esp,1 pop eax ret sleep_milliseconds: ;eax = time period in milliseconds xor edx,edx mov ecx,1000 div ecx imul edx,1000000 push edx ; tv_nsec push eax ; tv_sec sys SYS_NANOSLEEP,esp,0 add esp,8 ret exit: mov ebp,eax mov ebx,[handle_fb_map] cmp ebx,INVALID_HANDLE_VALUE jz .fb_map_closed sys SYS_MUNMAP,ebx,[handle_fb_map.len] .fb_map_closed: mov ebx,[handle_fb] cmp ebx,INVALID_HANDLE_VALUE jz .fb_closed sys SYS_CLOSE,ebx .fb_closed: sys SYS_EXIT,ebp It uses no libraries and doesn't need any external resources except for the OS kernel. It assumes that you have fb0 as your frame buffer device. It also assumes that you are using 32-bits/pixel. If either of those assumptions is wrong then it will probably look weird or just not work. You need to run it with admin privilege else it won't be able to access the frame buffer. Last edited by revolution on 25 Dec 2018, 16:17; edited 2 times in total |
|||
25 Dec 2018, 09:31 |
|
JohnFound 25 Dec 2018, 10:54
@revolution: It works on my system even without root, because fb0 device is in the group "video" where my user has access.
BTW, I can try to make a framebuffer version of FreshLib GUI part. The hard part will be that the library expects at least root level windows support from the OS. So I should somehow emulate windows in the OS interface layer. |
|||
25 Dec 2018, 10:54 |
|
revolution 25 Dec 2018, 12:17
JohnFound wrote: BTW, I can try to make a framebuffer version of FreshLib GUI part. The hard part will be that the library expects at least root level windows support from the OS. So I should somehow emulate windows in the OS interface layer. Actually I find it strange that I see nothing when the X windows are shown. I guess it uses a different buffer for display. I wonder how to get access to that buffer? |
|||
25 Dec 2018, 12:17 |
|
revolution 25 Dec 2018, 12:58
By way of comparison, here is a 64-bit version of framebuffer access:
Code: format ELF64 executable 3 entry main FRAME_BUFER_NAME equ '/dev/fb0' TEST_COLOUR = 0x00ffff00 ; Yellow TEST_DELAY = 2000 ; 2 seconds SYS_WRITE = 1 SYS_OPEN = 2 SYS_CLOSE = 3 SYS_MMAP = 9 SYS_MUNMAP = 11 SYS_IOCTL = 16 SYS_NANOSLEEP = 35 SYS_EXIT = 60 NULL = 0 HANDLE_STD_OUTPUT = 1 MAXIMUM_ERROR_NUMBER = -4096 INVALID_HANDLE_VALUE = -1 O_RDWR = 2 FBIOGET_VSCREENINFO = 0x4600 FBIOGET_FSCREENINFO = 0x4602 PROT_READ = 1 ;Page can be read PROT_WRITE = 2 ;Page can be written MAP_SHARED = 1 ;Share changes struc fb_fix_screeninfo { .id rb 16 ; identification string eg "TT Builtin" .smem_start rq 1 ; Start of frame buffer mem (physical address) .smem_len rd 1 ; Length of frame buffer mem .type rd 1 ; see FB_TYPE_* .type_aux rd 1 ; Interleave for interleaved Planes .visual rd 1 ; see FB_VISUAL_* .xpanstep rw 1 ; zero if no hardware panning .ypanstep rw 1 ; zero if no hardware panning .ywrapstep rw 1 ; zero if no hardware ywrap .align_0 rw 1 .line_length rd 1 ; length of a line in bytes .align_1 rd 1 .mmio_start rq 1 ; Start of Memory Mapped I/O (physical address) .mmio_len rd 1 ; Length of Memory Mapped I/O .accel rd 1 ; Indicate to driver which specific chip/card we have .capabilities rw 1 ; see FB_CAP_* .reserved rw 2 ; Reserved for future compatibility .align_2 rw 1 } struc fb_bitfield { .offset rd 1 ; beginning of bitfield .length rd 1 ; length of bitfield .msb_right rd 1 ; != 0 : Most significant bit is right } struc fb_var_screeninfo { .xres rd 1 ; visible resolution .yres rd 1 .xres_virtual rd 1 ; virtual resolution .yres_virtual rd 1 .xoffset rd 1 ; offset from virtual to visible .yoffset rd 1 ; resolution .bits_per_pixel rd 1 ; guess what .grayscale rd 1 ; 0 = color, 1 = grayscale, >1 = FOURCC .red fb_bitfield ; bitfield in fb mem if true color, .green fb_bitfield ; else only length is significant .blue fb_bitfield .transp fb_bitfield ; transparency .nonstd rd 1 ; != 0 Non standard pixel format .activate rd 1 ; see FB_ACTIVATE_* .height rd 1 ; height of picture in mm .width rd 1 ; width of picture in mm .accel_flags rd 1 ; (OBSOLETE) see fb_info.flags .pixclock rd 1 ; pixel clock in ps (pico seconds) .left_margin rd 1 ; time from sync to picture .right_margin rd 1 ; time from picture to sync .upper_margin rd 1 ; time from sync to picture .lower_margin rd 1 .hsync_len rd 1 ; length of horizontal sync .vsync_len rd 1 ; length of vertical sync .sync rd 1 ; see FB_SYNC_* .vmode rd 1 ; see FB_VMODE_* .rotate rd 1 ; angle we rotate counter clockwise .colorspace rd 1 ; colorspace for FOURCC-based modes .reserved rd 4 ; Reserved for future compatibility } segment readable writeable handle_fb dq INVALID_HANDLE_VALUE handle_fb_map dq INVALID_HANDLE_VALUE handle_fb_map.len dq ? fixed_screeninfo fb_fix_screeninfo variable_screeninfo fb_var_screeninfo segment readable frame_buffer_name: db FRAME_BUFER_NAME,0 success_opening_fb: db 'Open ',FRAME_BUFER_NAME,' okay (%)',10,0 success_reading_fixed_info: db 'Read fb_fix_screeninfo okay',10,0 success_reading_variable_info: db 'Read fb_var_screeninfo okay',10,0 show_fixed_info: db 'frame buff %',10 db 'frame len %',10 db 'mem start %',10 db 'mem len %',10 db 'line length %',10,0 show_variable_info: db 'x visible %',10 db 'y visible %',10 db 'x virtual %',10 db 'y virtual %',10 db 'x offset %',10 db 'y offset %',10 db 'pixel bits %',10,0 clean_exit: db 'Everything is okay',10,0 error_opening_fb: db 'Cannot open ',FRAME_BUFER_NAME,10,0 error_opening_fb.exit = 1 error_reading_fixed_info: db 'Cannot read fb_fix_screeninfo',10,0 error_reading_fixed_info.exit = 2 error_reading_variable_info: db 'Cannot read fb_var_screeninfo',10,0 error_reading_variable_info.exit = 3 error_allocating_fb_map: db 'Cannot allocate memory map for the frame buffer',10,0 error_allocating_fb_map.exit = 4 segment executable macro sys p1,p2,p3,p4,p5,p6,p7 { macro def reg,param \{ if ~ param eq & ~ reg eq param if param eqtype 0 & param = 0 xor reg,reg else mov reg,param end if end if \} def r9,p7 def r8,p6 def r10,p5 def rdx,p4 def rsi,p3 def rdi,p2 def rax,p1 syscall purge def } macro printf string,[parameter] { common local parameter_count parameter_count = 0 reverse if ~ parameter eq parameter_count = parameter_count + 1 push parameter end if common mov rax,string call simple_printf if parameter_count > 0 add rsp,parameter_count * 8 end if } main: sys SYS_OPEN,frame_buffer_name,O_RDWR,0 cmp rax,MAXIMUM_ERROR_NUMBER ja .error_opening_fb mov [handle_fb],rax printf success_opening_fb,rax sys SYS_IOCTL,[handle_fb],FBIOGET_FSCREENINFO,fixed_screeninfo test rax,rax jnz .error_reading_fixed_info printf success_reading_fixed_info sys SYS_IOCTL,[handle_fb],FBIOGET_VSCREENINFO,variable_screeninfo test rax,rax jnz .error_reading_variable_info printf success_reading_variable_info ;show some information that was discovered mov eax,[fixed_screeninfo.smem_len] mov ebx,[fixed_screeninfo.mmio_len] mov ecx,[fixed_screeninfo.line_length] printf show_fixed_info,[fixed_screeninfo.smem_start],rax,[fixed_screeninfo.mmio_start],rbx,rcx mov eax,[variable_screeninfo.xres] mov ebx,[variable_screeninfo.yres] mov ecx,[variable_screeninfo.xres_virtual] mov edx,[variable_screeninfo.yres_virtual] mov esi,[variable_screeninfo.xoffset] mov edi,[variable_screeninfo.yoffset] mov ebp,[variable_screeninfo.bits_per_pixel] printf show_variable_info,rax,rbx,rcx,rdx,rsi,rdi,rbp ;setup a place in memory to access the frame buffer mov eax,[variable_screeninfo.yres_virtual] mul [fixed_screeninfo.line_length] mov [handle_fb_map.len],rax sys SYS_MMAP,0,rax,PROT_READ or PROT_WRITE,MAP_SHARED,[handle_fb],0 cmp rax,MAXIMUM_ERROR_NUMBER ja .error_allocating_fb_map mov [handle_fb_map],rax ;draw a simple test mov rdi,[handle_fb_map] mov rax,TEST_COLOUR or (TEST_COLOUR shl 32) mov rcx,[handle_fb_map.len] shr rcx,3 cld rep stosq ;show this awesome test screen for a short period mov rax,TEST_DELAY call sleep_milliseconds ;everything worked printf clean_exit mov rax,NULL jmp exit .error_opening_fb: printf error_opening_fb mov rax,error_opening_fb.exit jmp exit .error_reading_fixed_info: printf error_reading_fixed_info mov rax,error_reading_fixed_info.exit jmp exit .error_reading_variable_info: printf error_reading_variable_info mov rax,error_reading_variable_info.exit jmp exit .error_allocating_fb_map: printf error_allocating_fb_map mov rax,error_allocating_fb_map.exit jmp exit simple_printf: ;rax = string ;stack = parameters ;supports only % to expand to an unsigned decimal number mov rbx,rsp mov rbp,rax .next_char: mov al,[rbp] inc rbp test al,al jz .done cmp al,'%' jnz .print_char add rbx,8 mov rax,[rbx] mov ecx,10 push -1 .next_digit: xor rdx,rdx div rcx push rdx test rax,rax jnz .next_digit .print_digits: pop rax test rax,rax js .next_char add al,'0' call simple_print_char jmp .print_digits .print_char: call simple_print_char jmp .next_char .done: ret simple_print_char: ;al = char push rax sys SYS_WRITE,HANDLE_STD_OUTPUT,rsp,1 pop rax ret sleep_milliseconds: ;rax = time period in milliseconds xor edx,edx mov ecx,1000 div rcx imul rdx,1000000 push rdx ; tv_nsec push rax ; tv_sec sys SYS_NANOSLEEP,rsp,0 add rsp,16 ret exit: mov rbp,rax mov rdi,[handle_fb_map] cmp rdi,INVALID_HANDLE_VALUE jz .fb_map_closed sys SYS_MUNMAP,rdi,[handle_fb_map.len] .fb_map_closed: mov rdi,[handle_fb] cmp rdi,INVALID_HANDLE_VALUE jz .fb_closed sys SYS_CLOSE,rdi .fb_closed: sys SYS_EXIT,rbp Last edited by revolution on 25 Dec 2018, 16:18; edited 1 time in total |
|||
25 Dec 2018, 12:58 |
|
revolution 25 Dec 2018, 14:09
Some research shows that only a subset of Linux drivers and kernels can support a buffer larger than the display. So unfortunately that means that double buffering by simply changing a pointer isn't possible on these systems.
One way around that is to create a dedicated back-buffer for drawing and copy the contents to the framebuffer during vsync. But again, not all Linux drivers and kernels support exposing vsync through IOCTL calls. Yuck. So now you have tearing and unsynchronised animations and videos with no way to fix it? This page suggests that the DRM interface can do it. Has anyone tried it? BTW: DRM here means Direct Rendering Manager, and not Digital Rights Management. Thankfully. |
|||
25 Dec 2018, 14:09 |
|
Furs 25 Dec 2018, 19:25
revolution wrote: Actually I find it strange that I see nothing when the X windows are shown. I guess it uses a different buffer for display. I wonder how to get access to that buffer? |
|||
25 Dec 2018, 19:25 |
|
revolution 26 Dec 2018, 01:39
But X must be using a buffer somewhere to draw the screen. Certainly it isn't accessed through fb0. Perhaps it uses the DRM/DRI interface. I haven't had a chance to try that yet.
|
|||
26 Dec 2018, 01:39 |
|
xpue 09 Jun 2019, 01:30
del
Last edited by xpue on 07 Jan 2024, 15:19; edited 1 time in total |
|||
09 Jun 2019, 01:30 |
|
revolution 09 Jun 2019, 02:02
xpue wrote: Just use opengl or vulkan, it probably will be faster. |
|||
09 Jun 2019, 02:02 |
|
xpue 09 Jun 2019, 07:52
del
Last edited by xpue on 07 Jan 2024, 15:19; edited 1 time in total |
|||
09 Jun 2019, 07:52 |
|
revolution 09 Jun 2019, 08:02
So does X setup this shared buffer with the GPU for each window?
Is what you describe for CPU code, or does it use the GPU engine? How does opengl or vulkan make this faster than our code? |
|||
09 Jun 2019, 08:02 |
|
xpue 09 Jun 2019, 09:12
del
Last edited by xpue on 07 Jan 2024, 15:20; edited 2 times in total |
|||
09 Jun 2019, 09:12 |
|
revolution 09 Jun 2019, 09:22
Do you have example code showing how to use opengl(/xv/vdpau/vaapi/etc), or the low level kernel calls that they use?
Can it co-exist with X? |
|||
09 Jun 2019, 09:22 |
|
xpue 13 Jun 2019, 15:56
del
Last edited by xpue on 07 Jan 2024, 15:20; edited 1 time in total |
|||
13 Jun 2019, 15:56 |
|
macgub 14 Jun 2019, 19:43
I tried run 64 bit version o revolution's framebuffer on fatdog as root. I got: can not open /dev/fb0. I used terminal emulator. Can someone explain problem?
|
|||
14 Jun 2019, 19:43 |
|
revolution 14 Jun 2019, 20:14
Can you run this command?
Code: dd if=/dev/urandom of=/dev/fb0 bs=4096 count=10 |
|||
14 Jun 2019, 20:14 |
|
Goto page Previous 1, 2, 3 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.