Server documentationBecause Linux is working in protection mode, user-mode processes cannot use the interrupt call provided in the graphics card BIOS as DOS to directly write the screen, therefore, Linux abstracts the FrameBuffer device for the user-state process to directly write the screen.
Before proceeding to the following sections, describe the background knowledge:
FrameBuffer is mainly implemented according to the VESA standard, so it can only implement the simplest functions.
Due to kernel problems, FrameBuffer is not allowed to modify the display mode after the system is up. (It seems that many people want to do this. This is not allowed. Of course, it can be implemented if you are self-driving)
The operations on FrameBuffer directly affect the output of all the consoles on the local machine, including the graphic interface of XWIN.
Well, now we can start to implement direct screen writing:
Open a FrameBuffer Device
Map the physical memory space of the video card to the user space by calling mmap.
Write memory directly.
Reference content is as follows: Fbtools. h
# Ifndef _ FBTOOLS_H _ # Define _ FBTOOLS_H _
# Include <linux/fb. h>
/* A framebuffer device structure */ Typedef struct fbdev { Int fb; Unsigned long fb_mem_offset; Unsigned long fb_mem; Struct fb_fix_screeninfo fb_fix; Struct fb_var_screeninfo fb_var; Char dev [20]; } FBDEV, * PFBDEV;
/* Open & init a frame buffer */ /* To use this function, You must set FBDEV. dev = "/dev/fb0" Or "/dev/fbX "*/ /* It's your frame buffer .*/ Int fb_open (PFBDEV pFbdev );
/* Close a frame buffer */ Int fb_close (PFBDEV pFbdev );
/* Get display depth */ Int get_display_depth (PFBDEV pFbdev );
/* Full screen clear */ Void fb_memset (void * addr, int c, size_t len );
# Endif
Fbtools. c
Code:
# Include <stdio. h> # Include <stdlib. h> # Include <fcntl. h> # Include <unistd. h> # Include <string. h> # Include <sys/ioctl. h> # Include <sys/mman. h> # Include <asm/page. h>
# Include "fbtools. h"
# Define TRUE 1 # Define FALSE 0 # Define MAX (x, y) (x)> (y )? (X) :( y )) # Define MIN (x, y) (x) <(y )? (X) :( y ))
/* Open & init a frame buffer */ Int fb_open (PFBDEV pFbdev) { PFbdev-> fb = open (pFbdev-> dev, O_RDWR ); If (pFbdev-> fb <0) { Printf ("Error opening % s: % m. Check kernel config \ n", pFbdev-> dev ); Return FALSE; } If (-1 = ioctl (pFbdev-> fb, FBIOGET_VSCREENINFO, & (pFbdev-> fb_var ))) { Printf ("ioctl FBIOGET_VSCREENINFO \ n "); Return FALSE; } If (-1 = ioctl (pFbdev-> fb, FBIOGET_FSCREENINFO, & (pFbdev-> fb_fix ))) { Printf ("ioctl FBIOGET_FSCREENINFO \ n "); Return FALSE; }
/* Map physics address to virtual address */ PFbdev-> fb_mem_offset = (unsigned long) (pFbdev-> fb_fix.smem_start )&(~ PAGE_MASK ); PFbdev-> fb_mem = (unsigned long int) mmap (NULL, pFbdev-> fb_fix.smem_len + PFbdev-> fb_mem_offset, PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev-> fb, 0 ); If (-1L = (long) pFbdev-> fb_mem) { Printf ("mmap error! Mem: % d offset: % d \ n ", pFbdev-> fb_mem, PFbdev-> fb_mem_offset ); Return FALSE; }
Return TRUE; }
/* Close frame buffer */ Int fb_close (PFBDEV pFbdev) { Close (pFbdev-> fb ); PFbdev-> fb =-1; }
/* Get display depth */ Int get_display_depth (PFBDEV pFbdev ); { If (pFbdev-> fb <= 0) { Printf ("fb device not open, open it first \ n "); Return FALSE; } Return pFbdev-> fb_var.bits_per_pixel; }
/* Full screen clear */ Void fb_memset (void * addr, int c, size_t len) { Memset (addr, c, len ); }
/* Use by test */ # Define DEBUG # Ifdef DEBUG Main () { FBDEV fbdev; Memset (& fbdev, 0, sizeof (FBDEV )); Strcpy (fbdev. dev, "/dev/fb0 "); If (fb_open (& fbdev) = FALSE) { Printf ("open frame buffer error \ n "); Return; }
Fb_memset (fbdev. fb_mem + fbdev. fb_mem_offset, 0, fbdev. fb_fix.smem_len );
Fb_close (& fbdev ); } |