日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

LINUX framebuffer

發布時間:2023/12/10 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LINUX framebuffer 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://wangshh03.blog.163.com/blog/static/49103415201001231317484/

一、FrameBuffer的原理

??? FrameBuffer 是出現在 2.2.xx 內核當中的一種驅動程序接口。

??? Linux是工作在保護模式下,所以用戶態進程是無法象DOS那樣使用顯卡BIOS里提供的中斷調用來實現直接寫屏,Linux抽象出 FrameBuffer這個設備來供用戶態進程實現直接寫屏。Framebuffer機制模仿顯卡的功能,將顯卡硬件結構抽象掉,可以通過 Framebuffer的讀寫直接對顯存進行操作。用戶可以將Framebuffer看成是顯示內存的一個映像,將其映射到進程地址空間之后,就可以直接進行讀寫操作,而寫操作可以立即反應在屏幕上。這種操作是抽象的,統一的。用戶不必關心物理顯存的位置、換頁機制等等具體細節。這些都是由 Framebuffer設備驅動來完成的。

??? Framebuffer本身不具備任何運算數據的能力,就只好比是一個暫時存放水的水池.CPU將運算后的結果放到這個水池,水池再將結果流到顯示器. 中間不會對數據做處理. 應用程序也可以直接讀寫這個水池的內容.在這種機制下,盡管Framebuffer需要真正的顯卡驅動的支持,但所有顯示任務都有CPU完成,因此CPU 負擔很重

framebuffer的設備文件一般是 /dev/fb0/dev/fb1 等等。

可以用命令: #dd if=/dev/zero of=/dev/fb 清空屏幕.

如果顯示模式是 1024x768-8 位色,用命令:$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768 清空屏幕;

用命令: #dd if=/dev/fb of=fbfile? 可以將fb中的內容保存下來;

可以重新寫回屏幕: #dd if=fbfile of=/dev/fb

在使用Framebuffer時,Linux是將顯卡置于圖形模式下的.

?

??? 在應用程序中,一般通過將 FrameBuffer 設備映射到進程地址空間的方式使用,比如下面的程序就打開 /dev/fb0 設備,并通過 mmap 系統調用進行地址映射,隨后用 memset 將屏幕清空(這里假設顯示模式是 1024x768-8 位色模式,線性內存模式):

?

int fb;

unsigned char* fb_mem;

fb = open ("/dev/fb0", O_RDWR);

fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);

memset (fb_mem, 0, 1024*768); //這個命令應該只有在root可以執行

?

??? FrameBuffer 設備還提供了若干 ioctl 命令,通過這些命令,可以獲得顯示設備的一些固定信息(比如顯示內存大小)、與顯示模式相關的可變信息(比如分辨率、象素結構、每掃描線的字節寬度),以及偽彩色模式下的調色板信息等等。

??? 通過 FrameBuffer 設備,還可以獲得當前內核所支持的加速顯示卡的類型(通過固定信息得到),這種類型通常是和特定顯示芯片相關的。比如目前最新的內核(2.4.9)中,就包含有對 S3MatroxnVidia3Dfx 等等流行顯示芯片的加速支持。在獲得了加速芯片類型之后,應用程序就可以將 PCI 設備的內存I/Omemio)映射到進程的地址空間。這些 memio 一般是用來控制顯示卡的寄存器,通過對這些寄存器的操作,應用程序就可以控制特定顯卡的加速功能。

??? PCI 設備可以將自己的控制寄存器映射到物理內存空間,而后,對這些控制寄存器的訪問,給變成了對物理內存的訪問。因此,這些寄存器又被稱為"memio"。一旦被映射到物理內存,Linux 的普通進程就可以通過 mmap 將這些內存 I/O 映射到進程地址空間,這樣就可以直接訪問這些寄存器了。

??? 當然,因為不同的顯示芯片具有不同的加速能力,對memio 的使用和定義也各自不同,這時,就需要針對加速芯片的不同類型來編寫實現不同的加速功能。比如大多數芯片都提供了對矩形填充的硬件加速支持,但不同的芯片實現方式不同,這時,就需要針對不同的芯片類型編寫不同的用來完成填充矩形的函數。

??? FrameBuffer 只是一個提供顯示內存和顯示芯片寄存器從物理內存映射到進程地址空間中的設備。所以,對于應用程序而言,如果希望在 FrameBuffer 之上進行圖形編程,還需要自己動手完成其他許多工作。

?

二、FrameBufferLinux中的實現和機制

Framebuffer對應的源文件在linux/drivers/video/目錄下。總的抽象設備文件為fbcon.c,在這個目錄下還有與各種顯卡驅動相關的源文件。?? //這個文件要好好看看

?

()、分析Framebuffer設備驅動

??? 需要特別提出的是在INTEL平臺上,老式的VESA 1.2 卡,如CGA/EGA卡,是不能支持Framebuffer的,因為Framebuffer要求顯卡支持線性幀緩沖,即CPU可以訪問顯緩沖中的每一位,但是VESA 1.2 卡只能允許CPU一次訪問64K的地址空間。

FrameBuffer設備驅動基于如下兩個文件:

1) linux/include/linux/fb.h

2) linux/drivers/video/fbmem.c

?

下面分析這兩個文件。

1fb.h

?? 幾乎主要的結構都是在這個中文件定義的。這些結構包括:

1fb_var_screeninfo

?? 這個結構描述了顯示卡的特性:

NOTE::::?? __u32 是表示 unsigned 不帶符號的 32 bits 的數據類型,其余類推。這是 Linux 內核中所用到的數據類型,如果是開發用戶空間(user-space)的程序,可以根據具體計算機平臺的情況,用 unsigned long 等等來代替

struct fb_var_screeninfo

{

__u32 xres; /* visible resolution */?? //可視區域

__u32 yres;

__u32 xres_virtual; /* virtual resolution */? //可視區域

__u32 yres_virtual;

__u32 xoffset; /* offset from virtual to visible resolution */ //可視區域的偏移

__u32 yoffset;

?

__u32 bits_per_pixel; /* guess what */? //每一象素的bit

__u32 grayscale; /* != 0 Gray levels instead of colors *///等于零就成黑白

?

struct fb_bitfield red; /* bitfield in fb mem if true color, */真彩的bit機構

struct fb_bitfield green; /* else only length is significant */

struct fb_bitfield blue;??

struct fb_bitfield transp; /* transparency */? 透明

?

__u32 nonstd; /* != 0 Non standard pixel format */ 不是標準格式

?

__u32 activate; /* see FB_ACTIVATE_* */

?

__u32 height; /* height of picture in mm */ 內存中的圖像高度

__u32 width; /* width of picture in mm */ 內存中的圖像寬度

?

__u32 accel_flags; /* acceleration flags (hints) */ 加速標志

?

/* Timing: All values in pixclocks, except pixclock (of course) */

?

時序-_-這些部分就是顯示器的顯示方法了,可以找相關的資料看看

__u32 pixclock; /* pixel clock in ps (pico seconds) */

__u32 left_margin; /* time from sync to picture */

__u32 right_margin; /* time from picture to sync */

__u32 upper_margin; /* time from sync to picture */

__u32 lower_margin;

__u32 hsync_len; /* length of horizontal sync */? 水平可視區域

__u32 vsync_len; /* length of vertical sync */?? 垂直可視區域

__u32 sync; /* see FB_SYNC_* */

__u32 vmode; /* see FB_VMODE_* */

__u32 reserved[6]; /* Reserved for future compatibility */ 備用-以后開發

};

?

2) fb_fix_screeninfon

這個結構在顯卡被設定模式后創建,它描述顯示卡的屬性,并且系統運行時不能被修改;比如FrameBuffer內存的起始地址。它依賴于被設定的模式,當一個模式被設定后,內存信息由顯示卡硬件給出,內存的位置等信息就不可以修改。

?

struct fb_fix_screeninfo {

char id[16]; /* identification string eg "TT Builtin" */ID

unsigned long smem_start; /* Start of frame buffer mem */ 內存起始

/* (physical address) */ 物理地址

__u32 smem_len; /* Length of frame buffer mem */ 內存大小

__u32 type; /* see FB_TYPE_* */

__u32 type_aux; /* Interleave for interleaved Planes */插入區域?

__u32 visual; /* see FB_VISUAL_* */

__u16 xpanstep; /* zero if no hardware panning */沒有硬件設備就為零

__u16 ypanstep; /* zero if no hardware panning */

__u16 ywrapstep; /* zero if no hardware ywrap */

__u32 line_length; /* length of a line in bytes */ 一行的字節表示

unsigned long mmio_start; /* Start of Memory Mapped I/O */內存映射的I/O起始

/* (physical address) */

__u32 mmio_len; /* Length of Memory Mapped I/O */ I/O的大小

__u32 accel; /* Type of acceleration available */ 可用的加速類型

__u16 reserved[3]; /* Reserved for future compatibility */

};

?

3) fb_cmap

描述設備無關的顏色映射信息。可以通過FBIOGETCMAP FBIOPUTCMAP 對應的ioctl操作設定或獲取顏色映射信息.

?

struct fb_cmap {

__u32 start; /* First entry */ 第一個入口

__u32 len; /* Number of entries */ 入口的數字

__u16 *red; /* Red values */

__u16 *green;

__u16 *blue;

__u16 *transp; /* transparency, can be NULL */ 透明,可以為零

};

?

4) fb_info

定義當顯卡的當前狀態;fb_info結構僅在內核中可見,在這個結構中有一個fb_ops指針, 指向驅動設備工作所需的函數集。

?

struct fb_info {

char modename[40]; /* default video mode */ 默認的視頻卡類型

kdev_t node;

int flags;

int open; /* Has this been open already ? */ 被打開過么?

#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */

struct fb_var_screeninfo var; /* Current var */ 現在的視頻信息

struct fb_fix_screeninfo fix; /* Current fix */ 修正的信息

struct fb_monspecs monspecs; /* Current Monitor specs */ 現在的顯示器模式

struct fb_cmap cmap; /* Current cmap */ 當前優先級

struct fb_ops *fbops;

char *screen_base; /* Virtual address */ 物理基址

struct display *disp; /* initial display variable */初始化

struct vc_data *display_fg; /* Console visible on this display */

char fontname[40]; /* default font name */默認的字體

devfs_handle_t devfs_handle; /* Devfs handle for new name */

devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */兼容

int (*changevar)(int); /* tell console var has changed */ 告訴console變量修改了

int (*switch_con)(int, struct fb_info*);

/* tell fb to switch consoles */ 告訴fb選擇consoles

int (*updatevar)(int, struct fb_info*);

/* tell fb to update the vars */ 告訴fb更新變量

void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */告訴fb使用黑白模式(或者不黑)

/* arg = 0: unblank */arg0的時候黑白模式

/* arg > 0: VESA level (arg-1) */ arg>0時候選擇VESA模式

void *pseudo_palette; /* Fake palette of 16 colors and

the cursor's color for non

palette mode */? 修正調色板

/* From here on everything is device dependent */ 現在就可以使用了

void *par;

};

?

5) struct fb_ops

用戶應用可以使用ioctl()系統調用來操作設備,這個結構就是用一支持ioctl()的這些操作的。

?

struct fb_ops {

/* open/release and usage marking */

struct module *owner;

int (*fb_open)(struct fb_info *info, int user);

int (*fb_release)(struct fb_info *info, int user);

/* get non settable parameters */

int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,

struct fb_info *info);

/* get settable parameters */

int (*fb_get_var)(struct fb_var_screeninfo *var, int con,

struct fb_info *info);

/* set settable parameters */

int (*fb_set_var)(struct fb_var_screeninfo *var, int con,

struct fb_info *info);

/* get colormap */

int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,

struct fb_info *info);

/* set colormap */

int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,

struct fb_info *info);

/* pan display (optional) */

int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,

struct fb_info *info);

/* perform fb specific ioctl (optional) */

int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,

unsigned long arg, int con, struct fb_info *info);

/* perform fb specific mmap */

int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);

/* switch to/from raster image mode */

int (*fb_rasterimg)(struct fb_info *info, int start);

};

?

6) structure map

struct fb_info_gen | struct fb_info | fb_var_screeninfo

?????????????????? |??????????????? | fb_fix_screeninfo

?????????????????? |??????????????? | fb_cmap

?????????????????? |??????????????? | modename[40]

???? ??????????????|??????????????? | fb_ops ---|--->ops on var

?????????????????? |??????????????? | ...?????? | fb_open

?????????????????? |??????????????? |?????????? | fb_release

?????????????????? |??????????????? |?????????? | fb_ioctl

?????????????????? |??????????????? |?????????? | fb_mmap

?????????????????? | struct fbgen_hwswitch?

?

????????????????????????????? \-----|-> detect

??????????????????????????????????? | encode_fix

??????????????????????????????????? | encode_var

????????????????????????? ??????????| decode_fix

??????????????????????????????????? | decode_var

??????????????????????????????????? | get_var

??????????????????????????????????? | set_var

??????????????????????????????????? | getcolreg

??????????????????????????????????? | setcolreg

??????????????????????????????????? | pan_display

??????????????????????????????????? | blank

??????????????????????????????????? | set_disp

?

?

[編排有點困難,第一行的第一條豎線和下面的第一列豎線對齊,第一行的第二條豎線和下面的第二列豎線對齊就可以了]

這個結構 fbgen_hwswitch抽象了硬件的操作.雖然它不是必需的,但有時候很有用.

2 fbmem.c

fbmem.c 處于Framebuffer設備驅動技術的中心位置.它為上層應用程序提供系統調用也為下一層的特定硬件驅動提供接口;那些底層硬件驅動需要用到這兒的接口來向系統內核注冊它們自己. fbmem.c 為所有支持FrameBuffer的設備驅動提供了通用的接口,避免重復工作.

?

1) 全局變量

?

struct fb_info *registered_fb[FB_MAX];

int num_registered_fb;

?

?

這兩變量記錄了所有fb_info 結構的實例,fb_info 結構描述顯卡的當前狀態,所有設備對應的fb_info 結構都保存在這個數組中,當一個FrameBuffer設備驅動向系統注冊自己時,其對應的fb_info 結構就會添加到這個結構中,同時num_registered_fb 為自動加1.

?

static struct {

const char *name;

int (*init)(void);

int (*setup)(void);

} fb_drivers[] __initdata= { ....};

?

如果FrameBuffer設備被靜態鏈接到內核,其對應的入口就會添加到這個表中;如果是動態加載的,即使用insmod/rmmod,就不需要關心這個表。

?

static struct file_operations fb_ops ={

owner: THIS_MODULE,

read: fb_read,

write: fb_write,

ioctl: fb_ioctl,

mmap: fb_mmap,

open: fb_open,

release: fb_release

};

這是一個提供給應用程序的接口.

?

2fbmem.c 實現了如下函數.

?

register_framebuffer(struct fb_info *fb_info);

unregister_framebuffer(struct fb_info *fb_info);

?

這兩個是提供給下層FrameBuffer設備驅動的接口,設備驅動通過這兩函數向系統注冊或注銷自己。幾乎底層設備驅動所要做的所有事情就是填充fb_info結構然后向系統注冊或注銷它。

?

(二)一個LCD顯示芯片的驅動實例

??? Skeleton LCD 控制器驅動為例,在LINUX中存有一個/fb/skeleton.cskeletonFramebuffer驅動程序,很簡單,僅僅是填充了 fb_info結構,并且注冊/注銷自己。設備驅動是向用戶程序提供系統調用接口,所以我們需要實現底層硬件操作并且定義file_operations 結構來向系統提供系統調用接口,從而實現更有效的LCD控制器驅動程序。

?

1)在系統內存中分配顯存

fbmem.c文件中可以看到, file_operations 結構中的open()release()操作不需底層支持,但read()write() mmap()操作需要函數fb_get_fix()的支持.因此需要重新實現函數fb_get_fix()。另外還需要在系統內存中分配顯存空間,大多數的LCD控制器都沒有自己的顯存空間,被分配的地址空間的起始地址與長度將會被填充到fb_fix_screeninfo 結構的smem_start smem_len 的兩個變量中.被分配的空間必須是物理連續的。

?

?

2)實現 fb_ops 中的函數

用戶應用程序通過ioctl()系統調用操作硬件,fb_ops 中的函數就用于支持這些操作。(注: fb_ops結構與file_operations 結構不同,fb_ops是底層操作的抽象,file_operations是提供給上層系統調用的接口,可以直接調用.

? ioctl()系統調用在文件fbmem.c中實現,通過觀察可以發現ioctl()命令與fb_opss 中函數的關系:

FBIOGET_VSCREENINFO fb_get_var

FBIOPUT_VSCREENINFO fb_set_var

FBIOGET_FSCREENINFO fb_get_fix

FBIOPUTCMAP fb_set_cmap

FBIOGETCMAP fb_get_cmap

FBIOPAN_DISPLAY fb_pan_display

?

?

如果我們定義了fb_XXX_XXX 方法,用戶程序就可以使用FBIOXXXX宏的ioctl()操作來操作硬件。

?

文件linux/drivers/video/fbgen.c或者linux/drivers/video目錄下的其它設備驅動是比較好的參考資料。在所有的這些函數中fb_set_var()是最重要的,它用于設定顯示卡的模式和其它屬性,下面是函數fb_set_var()的執行步驟:

?

1)檢測是否必須設定模式

2)設定模式

?

3)設定顏色映射

?

4) 根據以前的設定重新設置LCD控制器的各寄存器。

?

第四步表明了底層操作到底放置在何處。在系統內存中分配顯存后,顯存的起始地址及長度將被設定到 LCD控制器的各寄存器中(一般通過fb_set_var() 函數),顯存中的內容將自動被LCD控制器輸出到屏幕上。另一方面,用戶程序通過函數mmap()將顯存映射到用戶進程地址空間中,然后用戶進程向映射空間發送的所有數據都將會被顯示到LCD顯示器上。

?

三、FrameBuffer的應用

?

(一)、一個使用FrameBuffer的例子

?

FrameBuffer主要是根據VESA標準的實現的,所以只能實現最簡單的功能。

由于涉及內核的問題,FrameBuffer是不允許在系統起來后修改顯示模式等一系列操作。(好象很多人都想要這樣干,這是不被允許的,當然如果你自己寫驅動的話,是可以實現的).

FrameBuffer的操作,會直接影響到本機的所有控制臺的輸出,包括XWIN的圖形界面。

struct fb_info 中的char fontname[40]; /* default font name */默認的字體

就可以實現顯示的中文化----難道 籃點linux就是這樣搞得??

好,現在可以讓我們開始實現直接寫屏:

?

1、打開一個FrameBuffer設備

?

2、通過mmap調用把顯卡的物理內存空間映射到用戶空間

?

3、直接寫內存。

?

/********************************

File name : 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

?

/******************

File name : fbtools.c

*/

?

#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);

}

?

(二)基于Linux核心的漢字顯示的嘗試

我們以一個簡單的例子來說明字符顯示的過程。我們假設是在虛擬終端1/dev/tty1)下運行一個如下的簡單程序。

?

main ( )

{

puts("hello, world.\n");

}

?

puts 函數向缺省輸出文件(/dev/tty1)發出寫的系統調用write(2)。系統調用到linux核心里面對應的核心函數是console.c中的 con_write()con_write()最終會調用do_con_write( )。在do_con_write( )中負責把"hello, world.\n"這個字符串放到tty1對應的緩沖區中去。

do_con_write( )還負責處理控制字符和光標的位置。讓我們來看一下do_con_write()這個函數的聲明。

static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)

??? 其中tty是指向tty_struct結構的指針,這個結構里面存放著關于這個tty的所有信息(請參照 linux/include/linux/tty.h)。Tty_struct結構中定義了通用(或高層)tty的屬性(例如寬度和高度等)。在 do_con_write( )函數中用到了tty_struct結構中的driver_data變量。driver_data是一個vt_struct指針。在vt_struct結構中包含這個tty的序列號(我們正使用tty1,所以這個序號為1)。Vt_struct結構中有一個vc結構的數組vc_cons,這個數組就是各虛擬終端的私有數據。

?

static int do_con_write(struct tty_struct * tty, int from_user,const unsigned char *buf, int count)

{

struct vt_struct *vt = (struct vt_struct *)tty->driver_data;//我們用到了driver_data變量

. . . . .

currcons = vt->vc_num; file://我們在這里的vc_nums就是1

. . . . .

}

?

??? 要訪問虛擬終端的私有數據,需使用vc_conscurrcons.d指針。這個指針指向的結構含有當前虛擬終端上光標的位置、緩沖區的起始地址、緩沖區大小等等。

??? "hello, world.\n"中的每一個字符都要經過conv_uni_to_pc( )這個函數轉換成8位的顯示字符。這要做的主要目的是使不同語言的國家能把16位的UniCode碼映射到8位的顯示字符集上,目前還是主要針對歐洲國家的語言,映射結果為8位,不包含對雙字節(double byte)的范圍。

??? 這種UNICODE到顯示字符的映射關系可以由用戶自行定義。在缺省的映射表上,會把中文的字符映射到其他的字符上,這是我們不希望看到也是不需要的。所以我們有兩個選擇∶

?

不進行conv_uni_to_pc( )的轉換。

加載符合雙字節處理的映射關系,即對非控制字符進行11的不變映射。我們自己定制的符合這種映射關系的UNICODE碼表是direct.uni。要想查看/裝載當前系統的unicode映射表,可使外部命令loadunimap

經過conv_uni_to_pc( )轉換之后,"hello, world.\n"中的字符被一個一個地填寫到tty1的緩沖區中。然后do_con_write( )調用下層的驅動,把緩沖區中的內容輸出到顯示器上(也就相當于把緩沖區的內容拷貝到VGA顯存中去)。

?

sw->con_putcs(vc_conscurrcons.d, (u16 *)draw_from, (u16*)draw_to-(u16 *)draw_from, y, draw_x);

?

之所以要調用底層驅動,是因為存在不同的顯示設備,其對應VGA顯存的存取方式也不一樣。

上面的Sw->con_putcs( )就會調用到fbcon.c中的fbcon_putcs()函數(con_putcs是一個函數的指針,在Framebuffer模式下指向 fbcon_putcs()函數)。也就是說在do_con_write( )函數中是直接調用了fbcon_putcs()函數來進行字符的繪制。比如說在256色模式下,真正負責輸出的函數是void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,const unsigned short *s, int count, int yy, int xx)

?

顯示中文

??? 比如說我們試圖輸出一句中文∶putcs(你好\n );(你好的內碼為0xc4,0xe3,0xba,0xc3)。這時候會怎么樣呢,有一點可以肯定,"你好"肯定不會出現在屏幕上,國為核心中沒有漢字字庫,中文顯示就是無米之炊了.

??? 1 在負責字符顯示的void fbcon_cfb8_putcs( )函數中,原有操作如下∶對于每個要顯示的字符,依次從虛擬終端緩沖區中以WORD為單位讀取(低位字節是ASCII碼,高8位是字符的屬性),由于漢字是雙字節編碼方式,所以這種操作是不可能顯示出漢字的,只能顯示出xxxx_putcs()是一個一個VGA字符.

?

要解決的問題∶

確保在do_con_write( )uni_pc轉換不會改變原有編碼。一個很直接的實現方式就是加載一個我們自己定制的UNICODE映射表,loadunimapdirect.uni,或者直接把direct.uni置為核心的缺省映射表。

?

針對如上問題,我們要做的第一個嘗試方案是如下。

首先需要在核心中加載漢字字庫,然后修改fbcon_cfb8_putcs()函數,在 fbcon_cfb8_putcs( )中一次讀兩個WORD,檢查這兩個WORD的低位字節是否能拼成一個漢字,如果發現能拼成一個漢字,就算出這個漢字在漢字字庫中的偏移,然后把它當成一個16 x 16VGA字符來顯示。

?

試驗的結果表明∶

?

能夠輸出漢字,但仍有許多不理想的地方,比如說,輸出以半個漢字開始的一串漢字,則這半個漢字后面的漢字都會是亂碼。這是半個漢字的問題。

光標移動會破壞漢字的顯示。表現為,光標移動過的漢字會變成亂碼。這是因為光標的更新是通過xxxx_putc( )函數來完成的。

xxxx_putc( )函數與xxxx_putcs( )函數實現的功能類似,但是xxxx_putc()函數只刷新一個字符而不是一個字符串,因而xxxx_putc()的輸入參數是一個整數,而不是一個字符串的地址。Xxxx_putc( )函數的聲明如下∶void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)

?

??? 下一個嘗試方案就是同時修改xxxx_putcs( )函數和xxxx_putc()函數。為了解決半個漢字的問題,每一次輸出之前,都從屏幕當前行的起始位置開始掃描,以確定要輸出的字符是否落在半個漢字的位置上。如果是半個漢字的位置,則進行相應的調整,即從向前移動一個字節的位置開始輸出。

??? 這個方案有一個困難,即xxxx_putc( )函數不用緩沖區的地址,而是用一個整數作為參數。所以xxxx_putc( )無法直接利用相鄰的字符來判別該定符是否是漢字。

??? 解決方案是,利用xxxx_putc( )的光標位置參數(yy, xx),可以逆推出該字符在緩沖區中的位置。但仍有一些小麻煩,在Linux的虛擬終端下,用戶可能會上卷該屏幕(shift + pageup),導致光標的y座標和相應字符在緩沖區的行數不一致。相應的解決方案是,在逆推的過程中,考慮卷屏的參量。

??? 這樣一來,我們就又進了一步,得到了一個相對更好的版本。但仍有問題沒有解決。敲入turbonetcfg,會發現菜單的邊框字符也被當成漢字顯示。這是因為,這種邊框字符是擴展字符,也使用了字符的第8位,因而被當作漢字來顯示。例如,單線一的制表符內碼為0xC4,當連成一條長線就是由一連串0xC4 組成,而0xC4C4正是漢字哪。于是水平的制表符被一連串的哪字替代了。要解決這個問題就非常不容易了,因為制表符的種類比較多,而且垂直制表符與其后面字符的組合型式又多種多樣,因而很難判斷出相應位置的字符是不是制表符,從理論上說,無論采取什么樣的排除算法,都必然存在誤判的情況,因為總存在二義性,沒有充足的條件來推斷出當前字符究竟是制表符還是漢字。

??? 我們一方面尋找更好的排除組合算法,一方面試圖尋找其它的解決方案。要想從根本上解決定個問題,必須利用其它的輔助信息,僅僅從緩沖區的字符來判斷是不夠的。

??? 經過一番努力,我們發現,在UNIX中使用擴展字符時,都要先輸出字符轉義序列(Escape sequence)來切換當前字符集。字符轉義序列是以控制字符Esc為首的控制命令,在UNIX的虛擬終端中完成終端控制命令,這種命令包括,移動光標座標、卷屏、刪除、切換字符集等等。也就是說在輸出代表制表符的字符串之前,通常是要先輸出特定的字符轉義序列。在console.c里,有根據字符轉義序列命令來記錄字符狀態的變量。結合該變量提供的信息,就可以非常干凈地把制表符與漢字區別開來。

?

??? 在如上思路的指引下,我們又產生了新的解決方案。經過改動得到了另一各版本.

??? 在這個新版本上,turbonetcfg在初次繪制的時候,制表符與漢字被清晰地區分開來,結果是非常正確的。但還有新的問題存在 turbonetcfg 在重繪的時候(如切換虛擬終端或是移動鼠標光標的時候),制表符還是變成了漢字,因為重繪完全依賴于緩沖區,而這時用來記錄字符集狀態的變量并不反映當前字符集狀態。問題還是沒有最終解決。我們又回到了起點。∶( 看來問題的最終解決手段必須是把字符集的狀態伴隨每一個字符存在緩沖區中。讓我們來研究一下緩沖區的結構。每一個字符占用16bit的緩沖區,低8位是 ASCII值,完全被利用,高8位包含前景顏色和背景顏色的屬性,也沒有多余的空間可以利用。因而只能另外開辟新的緩沖區。為了保持一致性,我們決定在原來的緩沖區后面添加相同大小的緩沖區,用來存放是否是漢字的信息。

?

??? 也許有讀者會問,我們只需要為每個字符添加一bit的信息來標志是否是漢字就足夠了,為什么還要開辟與原緩沖區大小相同的雙倍緩沖區,是不是太浪費呢?我們先放下這個問題,稍后再作回答。

??? 其實,如果再添加一bit來標志是當前字符是漢字的左半邊還是右半邊的話,就會省去掃描屏幕上當前整行字符串的工作,這樣一來,編程會更簡單。但是有讀者會問,即使是這樣,使用8bit總夠用了吧?為什么還要使用16bit呢?

??? 我們的作法是∶用低8位來存放漢字另外一半的內碼,用高8位中的2 bit來存放上面所講的輔助信息,高8位的剩余6位可以用來存放漢字或其它編碼方式(如BIG5或日文、韓文)的信息,從而使我們可以實現同屏顯示多種雙字節語言的字符而不會有相互干擾。另外,在編程時,雙倍緩沖也比較容易計算。這樣我們就回答了如上的兩個問題。

??? 迄今為止,我們有了一套徹底解決漢字和制表符相互干擾、半個漢字的刷新、重繪等問題的方案。剩下的就是具體編程實現的問題了。

??? 但是,由于Framebuffer的驅動很多,修改每一個驅動的xxxx_putc()函數和xxxx_putcs( )函數會是一項不小的工作,而且,改動驅動程序后,每種驅動的測試也是很麻煩的,尤其是對于有硬件加速的顯卡,修改和測試會更不容易。那么,存不存在一種不需要修改顯卡驅動程序的方法呢?

??? 經過努力,我們發現,可以在調用xxxx_putcs( )xxxx_putc()函數輸出漢字之前,修改vga字庫的指針使其指向所需顯示的漢字在漢字字庫中的位置,即把一個漢字當成兩個vga ASCII字符輸出。也就是說,在內核中存在兩個字庫,一個是原有的vga字符字庫,另一個是漢字字庫,當我們需要輸出漢字的時候,就把vga字庫的指針指向漢字字庫的相應位置,漢字輸出完之后,再把該指針指向vga字庫的原有位置。

?? 這樣一來,我們只需要修改fbcon.cconsole.c,其中console.c負責維護雙倍緩沖區,把每一個字符的信息存入附加的緩沖區;而 fbcon.c負責利用雙倍緩沖區中附加的信息,調整vga字庫的指針,調用底層的顯示驅動程序。這里還有幾個需要注意的地方∶

?

由于屏幕重繪等原因,調用底層驅動xxxx_putc( )xxxx_putcs()的地方有多處。我們作了兩個函數分別包裝這兩個調用,完成替換字庫、調用xxxx_putcs( )xxxx_putc( )、恢復字庫等功能。

為了實現向上滾屏(shift + pageup)時也能看到漢字,我們需要作另外的修改。

??? Linux 在設計虛擬終端的時候,提供了回顧被卷出屏幕以外的信息的功能,這就是用熱鍵來向上滾屏(shift + pageup)。當前被使用的虛擬終端擁有一個公共的緩沖區(soft back),用來存放被滾出屏幕以外的信息。當切換虛擬終端的時候,公共緩沖區的內容會被清除而被新的虛擬終端使用。向上滾屏的時候,顯示的是公共緩沖區中的內容。因此,如果我們想在向上滾屏的時候看到漢字,公共緩沖區也必須加倍,以確保沒有信息丟失。當滾出屏幕的信息向公共緩沖區填寫的時候,必須把相應的附加信息也填寫進公共緩沖區的附加區域。這就要求fbcon.c必須懂得利用公共緩沖區的附加信息。

??? 當然,有另外一種偷懶的方法,那就是不允許用戶向上滾屏,從而避免對公區緩沖區的處理。

把不同的編碼方式(GBBIG5、日文和韓文)寫成不同的module,以實現動態加載,從而使得擴展新的編碼方式不需要重新編譯核心。

測試

?

本文實現的Kernel Patch文件(patch.kernel.chinese)可以從http://www.turbolinux.com.cn下載。Cd /usr/src/(該目錄下應有Linux核心源程序所在的目錄linux/ patch -p0 -b < patch.kernel.chinese make menuconfig 請選擇Console drivers選項中的

?

* Double Byte Character Display Support(EXPERIMENTAL)

* Double Byte GB encode (module only)

* VESA VGA graphics console

<*> Virtual Frame Buffer support (ONLY FOR TESTING!)

<*> 8 bpp packed pixels support

<*> 16 bpp packed pixels support

<*> VGA characters/attributes support

* Select compiled-in fonts

*VGA 8x8 font

*VGA 8x16 font

?

make dep

make bzImage

make modules

make install

make modules_install

?

然后用新的核心啟動。

?

Insmod encode-gb.o

?

四、其它

?

(一)?? 設置FrameBuffer

??? FrameBuffer,可以譯作"幀緩沖",有時簡稱為 fbdrv,基于fbdrvconsole也被稱之為fbcon。這是一種獨立于硬件的抽象圖形設備。FrameBuffer的優點在于其高度的可移植性、易使用性、穩定性。使用Linux內核的 FrameBuffer驅動(vesafb),可以輕松支持到1024X768X32bpp以上的分辯率。而且目前可得到的絕大多數linux版本所發行的內核中,已經預編譯了FrameBuffer支持,通常不需要重新編譯內核就可以使用。所以FrameBuffer也是zhcon推薦使用的驅動方式。

?

進入FrameBuffer可以簡單地在系統啟動時向kernel傳送vga=mode-number的參數來激活FrameBuffer設備,如:

lilo:linux vga=305

將會啟動1024x768x8bpp模式。

?

?????????? 640x480??? 800x600??? 1024x768??? 1280x1024

? 8 bpp????? 769????????? 771?????? 773??????? 775

? 16 bpp???? 785????????? 788?????? 791??????? 794

? 32 bpp???? 786????????? 789?????? 792??????? 795

?

(二)?? 要使linux缺省進入FrameBuffer,可以修改/etc/lilo.conf,加入一下語句:

vga=0x303

退出編輯,執行:

lilo -v

重新啟動linux,可以使其進入800x600256色模式。

grub也是一樣,在grub.conf中的kernel行后面寫上vga=xxx就行了,也可以用vga=ask,讓系統啟動的時候詢問你用多大的分辨率

?

(三)我編譯內核時,選擇framebuffer模式,啟動時屏幕上有一企鵝圖片,不知這是如何造成的這個圖片可以去掉或改動嗎?

可以將drivers/video/fbcon.c: fbcon_setup()if (logo) { } 代碼去掉

總結

以上是生活随笔為你收集整理的LINUX framebuffer的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

在线观看黄色免费视频 | 九九综合在线 | 日韩欧美在线视频一区二区三区 | 国产精品美女视频 | 国产精品一区在线观看你懂的 | 亚洲综合日韩在线 | 91成人免费在线 | 99精品在线视频播放 | 亚洲午夜精品久久久久久久久 | 中文字幕免费 | 日本在线视频一区二区三区 | 一区二区三区精品在线 | 午夜精品一区二区三区在线观看 | 九九九九精品九九九九 | 久热电影| 国产成人一区二区三区 | 一级黄色在线视频 | 91精品国产欧美一区二区成人 | 中文字幕成人在线观看 | 欧美性生活小视频 | 日韩av影视在线 | 成人小视频在线免费观看 | 99久久超碰中文字幕伊人 | 久艹视频免费观看 | 亚洲开心激情 | 在线免费国产视频 | 视频一区二区在线 | 午夜精品一区二区三区可下载 | 狠狠躁日日躁狂躁夜夜躁 | 美女免费视频观看网站 | 97av在线| 国产视频精品在线 | 欧美日韩成人一区 | 久久久综合| 久久国产热视频 | 欧美天堂影院 | 婷婷性综合 | 99精品视频一区 | 综合天天网 | 亚洲精品乱码久久久久久9色 | 日韩在线一区二区免费 | 久久av福利 | 久久久久99999 | 手机成人av | 亚洲精品午夜久久久 | 欧美韩国在线 | 97色在线视频 | 国产一级片免费观看 | 日日夜夜综合 | 久久综合九色九九 | 欧美在线a视频 | 99国产精品久久久久久久久久 | 国产伦理一区二区 | 国产视频一区二区在线播放 | 成人久久精品 | 日本公妇在线观看高清 | 精品uu| 国产午夜亚洲精品 | 91精品视频在线观看免费 | 骄小bbw搡bbbb揉bbbb | 五月婷婷av| 欧美性脚交 | 久久激情视频 久久 | 午夜视频一区二区三区 | 日韩免费久久 | 精品国产免费av | 99久久精品国产亚洲 | 成人小视频在线观看免费 | 国产激情小视频在线观看 | 色www永久免费 | 91精品国产高清自在线观看 | 国产99久久久国产精品免费看 | 久久综合九色综合欧美就去吻 | 国产成a人亚洲精v品在线观看 | 日韩 精品 一区 国产 麻豆 | 中文字幕第一页在线视频 | 亚洲视频www| 免费精品在线 | 国产网站色| 麻豆免费视频观看 | 国产午夜精品一区二区三区欧美 | 天天天天射| 夜添久久精品亚洲国产精品 | 成人免费毛片aaaaaa片 | 99久热在线精品视频成人一区 | 日韩高清免费电影 | 国产99精品 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 亚洲欧美精品一区 | 碰超人人 | 久久观看| 国产精品久久久久久影院 | 久久国产精品一区二区三区四区 | www.色午夜| 日韩高清国产精品 | 91香蕉视频在线 | 久久精品国产一区二区三区 | 97精品欧美91久久久久久 | 午夜精品一区二区三区免费视频 | 99精品毛片| 一区二区视频欧美 | 中文字幕 第二区 | av免费在线观看网站 | 久久se视频 | 国产日韩欧美在线一区 | 国产手机在线播放 | 国产在线精品一区二区三区 | 精品99在线 | 亚洲情婷婷 | 天天爽网站 | 色之综合网 | 国产精品久久视频 | 国产精品久久久久毛片大屁完整版 | 麻花传媒mv免费观看 | 韩国精品福利一区二区三区 | 2019精品手机国产品在线 | 国产亚洲精品美女 | 黄色片免费电影 | 99热国产在线中文 | 久久国产午夜精品理论片最新版本 | 亚洲美女精品视频 | 天天操天天操 | 啪啪免费观看网站 | 丁香婷婷基地 | 91探花系列在线播放 | 激情欧美xxxx | 免费看av片网站 | 亚洲日本在线视频观看 | 久久99精品一区二区三区三区 | 久久精品国产免费看久久精品 | 成人av一区二区三区 | 国产小视频免费观看 | 久久久麻豆视频 | 国产精品视频免费看 | 最近日韩免费视频 | 在线天堂中文在线资源网 | 天天综合狠狠精品 | 国产精品视频999 | 在线免费黄色片 | www.黄色片网站 | 国产午夜精品av一区二区 | 久久99网| 中文字幕av在线免费 | 亚洲精品h| 亚洲黄色在线免费观看 | 四虎在线免费观看 | 国产精品99久久久久久人免费 | 美腿丝袜av| 婷婷中文字幕 | 亚洲网站在线看 | 97视频在线看 | 国产精品正在播放 | 免费国产在线视频 | 国产黄色在线网站 | 久久国产成人午夜av影院潦草 | 天天干天天操天天干 | 久久精品一二区 | 一区二区视频免费在线观看 | www.色就是色| 免费看一级黄色大全 | 视频在线亚洲 | 亚洲国产美女久久久久 | 日韩网站免费观看 | 国产精品二区在线 | 免费观看一级成人毛片 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 亚洲男男gⅴgay双龙 | 国产精品久久久久久久免费观看 | 狠狠狠狠狠狠狠狠干 | 久久久久久久久网站 | 在线播放亚洲激情 | 97超碰在线人人 | 天天干天天碰 | 97精品免费视频 | www.玖玖玖| 国产中文伊人 | 亚洲老妇xxxxxx | 在线观看日韩国产 | 日韩精品中文字幕在线观看 | 国产小视频免费在线网址 | 色av资源网 | 日日操操操 | 国产亚洲精品bv在线观看 | 国产色婷婷 | 在线草 | 在线观看aa| 久久激情电影 | 久久精品久久久久久久 | 免费在线观看国产黄 | 午夜精品久久久久久 | 亚洲欧美国产精品va在线观看 | 中文字幕免费久久 | 99免费在线播放99久久免费 | 免费看国产曰批40分钟 | 日本激情视频中文字幕 | 人人爱爱人人 | 欧美日韩高清免费 | www.com黄色| 免费看亚洲毛片 | 麻豆播放| 91久久电影 | 91亚洲精品在线 | 操天天操 | 日韩精品影视 | 97超碰中文字幕 | 日韩精品中文字幕久久臀 | 日韩精品视频在线观看免费 | 三级av黄色| 91久久在线观看 | 久久久久亚洲天堂 | 日本xxxx裸体xxxx17 | 91传媒激情理伦片 | 中文字幕在线观看第三页 | 日韩av看片| 一区二区三区免费在线观看视频 | 在线免费黄色毛片 | 亚洲第一成网站 | 在线亚洲小视频 | 国产精品一区二区在线看 | 日韩高清不卡一区二区三区 | 99精品视频在线观看免费 | 激情综合婷婷 | 精品国产a | 亚洲高清在线视频 | 这里只有精彩视频 | 久久www免费人成看片高清 | 久久久久久久久久影视 | 色99久久 | 亚洲激情在线视频 | 丁香激情五月 | 激情综合狠狠 | 久久香蕉一区 | 亚洲国产中文字幕在线观看 | 欧美色就是色 | www.久久91 | 久久国产精品久久精品 | 国产一级精品视频 | 二区在线播放 | 视频在线观看亚洲 | www.av在线.com| 黄色片免费在线 | 国产理论免费 | 国产中文字幕视频在线观看 | av中文国产 | 免费91麻豆精品国产自产在线观看 | 国产91精品一区二区绿帽 | 特黄特色特刺激视频免费播放 | 久久草av| 一级片色播影院 | 欧美精品xxx | 日韩色区 | 激情网在线视频 | 蜜臀久久99精品久久久无需会员 | 亚洲黄污| 国产成人久久精品一区二区三区 | 91大神免费视频 | 国产在线第三页 | 国产精品视频最多的网站 | 日韩久久精品一区二区 | 日韩色综合网 | 亚洲精品在线观 | 亚洲视频每日更新 | 日韩视频a | 欧美在线视频免费 | 国产看片 色 | 亚洲精品国产精品国 | 99热最新精品 | av福利在线免费观看 | 婷婷综合激情 | 97在线视频免费观看 | 高潮久久久久久久久 | 在线av资源 | 精品特级毛片 | 中文在线中文资源 | 亚洲理论在线 | 最近免费观看的电影完整版 | 在线观看黄色 | 久艹视频在线免费观看 | 久久综合久色欧美综合狠狠 | 久草在线最新免费 | 精品视频在线看 | 99精品免费久久久久久久久 | 九九爱免费视频 | 国产高清免费观看 | 国产精品久久久久国产精品日日 | 国产婷婷vvvv激情久 | 四虎影视精品永久在线观看 | 丝袜美腿在线播放 | 国产精品欧美激情在线观看 | 久久se视频 | 十八岁以下禁止观看的1000个网站 | 日韩欧美在线免费 | 午夜国产福利在线观看 | 91av在线国产| 亚洲综合网站在线观看 | 天天av天天 | 天天色天天射天天综合网 | 在线观看视频一区二区三区 | 久草精品视频 | 91精品在线免费 | 国产精品亚洲人在线观看 | 丁香六月婷 | 国内毛片毛片 | 亚洲二区精品 | 欧美精彩视频在线观看 | 久99久中文字幕在线 | 又黄又刺激又爽的视频 | 欧美精品乱码久久久久久按摩 | 97福利在线 | 99精品欧美一区二区三区黑人哦 | 96亚洲精品久久久蜜桃 | 亚洲撸撸| 97色婷婷| 国语麻豆| 亚洲精品国产日韩 | 日韩精品在线看 | 国产一区免费观看 | 成人精品视频久久久久 | 国产一区二区观看 | 日韩在线视 | 欧美与欧洲交xxxx免费观看 | 亚洲日韩精品欧美一区二区 | 免费久久久久久久 | 激情视频一区二区三区 | 国产亚洲婷婷免费 | 国产精品 中文在线 | 日精品在线观看 | 999久久a精品合区久久久 | av在线电影播放 | 色天天综合网 | 午夜精品一区二区国产 | 一级淫片在线观看 | 99在线观看精品 | 999成人 | 亚洲国产资源 | 国产美女网站视频 | 天天干天天综合 | 国内精品久久久久影院优 | 久久综合九色综合欧美狠狠 | 五月婷婷一区二区三区 | 99欧美精品| 国产精品第一 | 麻豆视频国产精品 | 欧美成年人在线观看 | 久久久91精品国产一区二区精品 | 一区二区高清在线 | 色综合久久网 | 国产毛片aaa | 亚洲国产精品小视频 | 国内精品视频久久 | 国产一级二级av | 五月综合婷 | 国产在线一线 | av中文字幕日韩 | 粉嫩av一区二区三区入口 | 在线观看视频三级 | 五月激情亚洲 | 丁香高清视频在线看看 | 天天射天天爱天天干 | 日本久久视频 | 在线日韩精品视频 | 亚洲理论片 | 成人国产精品一区二区 | 天天操天天添 | 69国产成人综合久久精品欧美 | 色综合久久五月 | 日韩免费区 | 国产九九九精品视频 | 亚洲国产福利视频 | 国产中文字幕在线视频 | 国产精品中文字幕av | 91理论片午午伦夜理片久久 | 欧美91精品久久久久国产性生爱 | 伊甸园av在线 | 亚洲黄色a | 亚洲精品在线观看视频 | 国产一级片不卡 | 99久久精品国产毛片 | 在线观看的av | 激情一区二区三区欧美 | 五月天激情开心 | 91麻豆精品国产自产 | 欧美一二三区播放 | 97在线观视频免费观看 | 亚洲精品网址在线观看 | 日韩午夜电影网 | 91视频 - x99av | 欧美在线久久 | 在线观看视频你懂得 | 成av在线 | 日本韩国精品一区二区在线观看 | 午夜少妇av | 国产手机在线观看 | 国产精品大片免费观看 | 欧美精品一区二区在线播放 | 天天插日日插 | 国产精品久久99精品毛片三a | 亚洲粉嫩av | 精品国内自产拍在线观看视频 | 99久精品视频 | 亚洲91精品 | 狠狠干狠狠色 | 在线观看mv的中文字幕网站 | 婷婷五月在线视频 | 日韩在线中文字幕 | 蜜臀av性久久久久av蜜臀妖精 | 国产玖玖在线 | 手机在线免费av | 91视频免费| 五月天激情综合 | 亚州av一区| 国产 日韩 中文字幕 | 国内精品中文字幕 | 欧美极品一区二区三区 | 毛片美女网站 | 亚洲成人黄 | 亚洲欧美日韩国产一区二区三区 | 伊人亚洲综合网 | av免费观看高清 | 97超碰在线久草超碰在线观看 | 性色视频在线 | 91精品一| 五月开心六月婷婷 | 日韩精品欧美一区 | 在线中文字幕av观看 | 国产精品久久久久久久久久直播 | 亚洲成人av一区 | 91精品国产99久久久久 | 国产91成人在在线播放 | av在线免费观看不卡 | 久久九九免费视频 | 高清不卡毛片 | 久久免费美女视频 | 国产.精品.日韩.另类.中文.在线.播放 | 91超碰免费在线 | 天天操狠狠操 | 亚洲更新最快 | 成人av网站在线观看 | 亚洲婷婷网 | 国产日韩欧美在线 | 91在线在线观看 | 成人黄色在线看 | 久久久人人爽 | 综合色影院 | 成人超碰在线 | 亚洲黄色一级电影 | 免费亚洲片 | 成人久久18免费网站图片 | 免费看的黄网站 | 中文字幕观看在线 | 不卡视频一区二区三区 | 国产亚洲精品久久久久久久久久久久 | 欧美色图东方 | 在线成人免费 | 最近日韩免费视频 | 91福利社区在线观看 | 久久久久久久久久久福利 | 九七视频在线观看 | 国产精品一区二区中文字幕 | 欧美日韩高清一区二区 | 丝袜美女在线 | 五月婷婷久久综合 | 久久视频免费看 | 美腿丝袜一区二区三区 | 亚洲精品一区二区网址 | 国产精品美女视频 | 久久99网站| 亚洲日本在线视频观看 | 亚洲性少妇性猛交wwww乱大交 | 激情五月婷婷综合网 | 中日韩在线视频 | 久99久在线 | 天天综合在线观看 | 黄p在线播放 | av黄色av | 久久视频精品 | 国产精品欧美一区二区三区不卡 | 国产成人黄色 | 午夜在线看片 | 日韩在线高清 | 成人黄色短片 | 永久免费的啪啪网站免费观看浪潮 | 一区二区视频电影在线观看 | 免费久久精品视频 | 免费电影一区二区三区 | 最新中文字幕在线观看视频 | 一区二区三区免费看 | 色综合久久88色综合天天免费 | 久久经典国产视频 | 日日操操操 | 国产精品一区二区三区在线看 | 色偷偷人人澡久久超碰69 | 国产短视频在线播放 | 天天爽天天爽天天爽 | 免费观看第二部31集 | 91成人免费 | 黄色大片日本 | 亚洲综合欧美激情 | 亚洲欧美激情插 | 伊人狠狠色丁香婷婷综合 | 精品视频一区在线观看 | 亚洲天堂网视频在线观看 | 国产精品av久久久久久无 | av网站在线免费观看 | 亚洲精品乱码久久久久久 | 99久高清在线观看视频99精品热在线观看视频 | 欧美午夜a | 91精品国产乱码久久桃 | 亚洲最大成人免费网站 | 精品亚洲va在线va天堂资源站 | 成人国产一区二区 | 欧洲精品久久久久毛片完整版 | 一区二区三区四区在线 | 国产福利a | 国产在线精品观看 | 国产毛片久久 | 亚洲精品乱码久久久久久蜜桃91 | 亚洲午夜精 | 亚洲黄网站 | 日本视频网 | 天天操天天插 | 欧美在线视频一区二区 | 欧洲一区精品 | 98涩涩国产露脸精品国产网 | 亚洲成人av在线播放 | 国产成人一区二区三区 | 在线国产中文字幕 | 99久久精品免费看国产 | 久久有精品 | 九九免费观看全部免费视频 | 日韩高清一区二区 | 久久人操| 人人舔人人插 | 国产精品久久久久久久久久久久午 | 亚洲精品乱码久久久久久蜜桃91 | 亚洲精品免费在线观看 | 欧美热久久 | 亚洲日本一区二区在线 | 久久不射影院 | 91成人免费在线 | 综合色在线观看 | 最近中文字幕mv免费高清在线 | 91成熟丰满女人少妇 | 久久成人视屏 | 天堂av免费观看 | 99久久久久久国产精品 | 又爽又黄又刺激的视频 | 亚洲成人网av | 精品伊人久久久 | 视频一区二区免费 | 成年免费在线视频 | 久草观看| 亚洲精品66 | 久久国产精品视频 | 欧美日在线观看 | 久久黄页 | 日日日爽爽爽 | 国产午夜精品理论片在线 | 国产一级免费片 | 中文字幕在线看视频国产中文版 | 精品国产精品久久一区免费式 | 色婷婷综合在线 | 天天射天天 | 亚洲资源一区 | www最近高清中文国语在线观看 | 99精品国产99久久久久久福利 | 久久久精品 | av一本久道久久波多野结衣 | 国产精品中文字幕av | 精品999 | 久99久在线视频 | 日韩欧美视频在线播放 | 久久久91精品国产一区二区精品 | 免费观看一级成人毛片 | 视频福利在线 | 69国产成人综合久久精品欧美 | 日韩中文字幕在线不卡 | 久久男人影院 | www.亚洲| 国产精品理论片在线播放 | 伊色综合久久之综合久久 | 99久久99久久精品 | 国产一区二区在线影院 | 国产一级在线观看 | av日韩精品 | 中文字幕一区二区三区乱码在线 | 午夜男人影院 | 日韩视频免费在线观看 | 97日日碰人人模人人澡分享吧 | 在线午夜电影神马影院 | 一区二区欧美在线观看 | 国产又粗又猛又黄 | 国产999精品 | 黄色毛片在线观看 | 日韩在线播放欧美字幕 | 狠狠综合| 欧美日韩国产mv | 天天操天天射天天添 | 美女久久精品 | 一区二精品 | 欧美人人爱 | 狠狠色丁香婷婷综合久小说久 | 九九九电影免费看 | 欧美日韩免费在线视频 | 成人免费一区二区三区在线观看 | 亚洲一二三区精品 | 欧美激情精品 | 久久伦理电影 | 毛片基地黄久久久久久天堂 | 国产视频一级 | 国产精品久久久久久久久久免费看 | 人人爽人人爱 | 国产精品久久久一区二区 | 亚洲一级电影在线观看 | 国产精品麻豆果冻传媒在线播放 | 色婷婷综合久色 | 久久精品免费 | 久久综合婷婷综合 | 免费亚洲黄色 | 色永久免费视频 | 97超碰中文字幕 | 国产高清在线免费观看 | 免费看v片| 国产成人在线免费观看 | 91在线看视频免费 | 免费视频三区 | 日韩欧美69| 九九爱免费视频在线观看 | 91久久久久久久一区二区 | 欧美最爽乱淫视频播放 | 激情网五月天 | 成人久久久久久久久 | 一本一本久久a久久精品综合妖精 | 亚洲综合激情小说 | 久草在线精品观看 | 中文成人字幕 | 久久久久高清 | 狠狠色丁香婷婷综合视频 | 亚洲精品在线观看不卡 | 午夜精品久久久久久久久久久 | 欧美日本中文字幕 | 亚洲人人精品 | 色婷婷五 | 免费电影播放 | 亚洲一区欧美精品 | 久久精品看片 | 亚洲午夜在线视频 | 懂色av一区二区三区蜜臀 | 六月激情丁香 | 国产伦精品一区二区三区四区视频 | 成人av免费在线 | 国产高清成人 | 免费看黄色小说的网站 | 99九九免费视频 | 欧美日韩一区二区三区不卡 | 国产一区二区三区免费观看视频 | 亚洲国产精品成人va在线观看 | 天天干婷婷 | 成人黄色片免费 | 91视频免费播放 | 99久久久久| 国产精品久久久免费 | 91精品国产乱码久久桃 | 91理论片午午伦夜理片久久 | 人操人| 日本久久久久久 | 日韩精品 在线视频 | 欧美一级大片在线观看 | 一区二区国产精品 | www久久精品 | 国产精品久久一卡二卡 | 91视频 - 88av | 欧美日韩视频在线一区 | 欧美在线视频精品 | 九九色网 | 成人精品在线 | 亚洲男男gaygayxxxgv | 成人性生交视频 | 四虎永久免费在线观看 | 国内精品久久影院 | 欧美日韩一区二区三区在线免费观看 | 亚洲国产精品电影 | 81精品国产乱码久久久久久 | 日韩精品综合在线 | 午夜精品视频一区 | av电影免费在线看 | 精品国产一区二区三区日日嗨 | 国产精品视频久久久 | 午夜精品福利一区二区三区蜜桃 | 亚洲久草在线 | 久久99精品一区二区三区三区 | 日本xxxx裸体xxxx17 | 久青草视频在线观看 | av电影亚洲 | 中文字幕日韩av | 久久久久久久久久久久久久av | 色悠悠久久综合 | 国产伦理精品一区二区 | 日韩在线观 | 国产色 在线 | 欧美日韩国产二区 | 久久久久久久亚洲精品 | 99久久影院 | 日韩亚洲欧美中文字幕 | 亚洲在线免费视频 | 99久久99久久精品国产片果冰 | 日韩在线观看视频中文字幕 | 超碰在线最新网址 | 国产人成在线视频 | 欧美激情综合五月色丁香 | 精品国产精品一区二区夜夜嗨 | 欧美激情操 | 欧美另类v | 九九久久久久99精品 | 欧美片网站yy | 婷婷午夜| 成人精品视频久久久久 | 欧美日本国产在线观看 | 国偷自产中文字幕亚洲手机在线 | 国产一级大片免费看 | 欧美日韩在线网站 | 亚洲精品xxx| 四虎影视av| 国产福利精品一区二区 | 91麻豆精品国产91久久久久 | 久久综合激情 | 麻豆av一区二区三区在线观看 | 亚洲黄色成人网 | 操操综合网| 插久久| 中文字幕成人在线 | 日韩高清观看 | 日韩av片免费在线观看 | 免费观看v片在线观看 | 国产精品欧美激情在线观看 | 亚洲欧美日韩国产一区二区三区 | 激情小说网站亚洲综合网 | 久久久久国产一区二区三区 | 亚洲资源在线 | 日日麻批40分钟视频免费观看 | 日韩中文字 | 欧美一级特黄高清视频 | 看av在线| 三级在线国产 | 日韩av一区二区在线播放 | 国产啊v在线 | 国产一区二区三区免费视频 | 日韩av手机在线观看 | 国产又粗又猛又黄 | 九九热精品视频在线观看 | 国产在线 一区二区三区 | 久草电影在线观看 | 69av免费视频 | 欧美 日韩 国产 中文字幕 | 成人在线视频在线观看 | 日韩欧美一区二区三区在线 | 热久久99这里有精品 | 国产91勾搭技师精品 | 91探花国产综合在线精品 | 97精品国产97久久久久久免费 | 国内精品在线看 | 欧美动漫一区二区三区 | 五月综合色婷婷 | 欧美成亚洲 | 国产精品久久久久久久久久 | 在线观看av的网站 | 亚洲全部视频 | 97操碰| 久久香蕉国产 | 欧美性护士| 高潮毛片无遮挡高清免费 | 色婷婷国产在线 | 又黄又刺激视频 | 不卡电影免费在线播放一区 | 国产在线国偷精品产拍免费yy | 久久精品超碰 | 最近中文字幕第一页 | 国产午夜精品一区二区三区在线观看 | 久久最新网址 | av一区二区在线观看中文字幕 | 99久热在线精品视频成人一区 | .国产精品成人自产拍在线观看6 | 天天躁天天狠天天透 | 在线免费观看羞羞视频 | 亚洲激色 | 国产精品第一 | 欧美精选一区二区三区 | 国产aaa毛片 | 成人在线一区二区 | 中国一级片在线观看 | 最近字幕在线观看第一季 | 国产小视频在线播放 | 日韩电影在线看 | 免费大片av | 成人在线黄色电影 | av成人在线电影 | www色| 国产xxxx性hd极品 | 国产精品黑丝在线观看 | 久久另类小说 | 网站你懂的 | 成人免费电影 | 精品一区av | a级国产乱理论片在线观看 特级毛片在线观看 | 91av视屏| 久久九九国产视频 | 在线日韩精品视频 | 中文字幕在线观看免费高清完整版 | 中文字幕一区二区三区久久蜜桃 | 午夜在线日韩 | 精品视频不卡 | 亚洲精品资源在线 | 中文字幕乱码电影 | 亚洲天堂网在线视频 | 人人人爽| 国产精品午夜在线观看 | 亚洲综合黄色 | 激情丁香5月| 久久久久成 | 久久伊人五月天 | 欧美色噜噜 | 91精品啪在线观看国产 | 中文字幕一二三区 | 久久精品视频在线播放 | 久久久久成| 在线观看v片| 久久精品com | 天天舔夜夜操 | 久久99视频免费观看 | 亚洲精品456在线播放第一页 | www蜜桃视频 | 国产午夜精品一区二区三区在线观看 | 国产亚洲免费观看 | 国产91成人在在线播放 | 免费看久久 | 国产人成一区二区三区影院 | 亚洲精品乱码久久久久久按摩 | 日本系列中文字幕 | 高清不卡毛片 | 天天天天色综合 | 日韩免费一区 | 亚洲成人av片在线观看 | 国产精品系列在线观看 | 五月婷婷开心 | 久久亚洲综合国产精品99麻豆的功能介绍 | 国产成人精品午夜在线播放 | 国产人成一区二区三区影院 | 在线观看色网站 | 日本不卡一区二区三区在线观看 | 看片的网址 | 精品国产大片 | 97人人澡人人添人人爽超碰 | 国产精品video | 日韩免费在线播放 | av色综合 | 精品免费久久 | 97电影在线看视频 | 久久久亚洲精华液 | 久久综合之合合综合久久 | 日本乱视频 | 色视频成人在线观看免 | 一级a性色生活片久久毛片波多野 | av三级在线看 | 天天拍夜夜拍 | 欧美日韩久久不卡 | 日韩在线首页 | 国产福利91精品张津瑜 | av丝袜在线 | 五月香视频在线观看 | 亚洲国产合集 | 日本一区二区不卡高清 | 午夜精品久久久久久久99水蜜桃 | 亚洲综合少妇 | 91丨九色丨国产丨porny精品 | 免费影视大全推荐 | 国产在线观看中文字幕 | 亚洲午夜久久久久 | 免费裸体视频网 | 天天综合网 天天综合色 | 国产精品一区二区久久久久 | 日韩欧美视频在线 | 亚洲一区二区精品在线 | 国产精品久久久久久久久久直播 | 亚洲精品日韩一区二区电影 | 日韩免费看片 | 夜夜干夜夜 | 久久久久久久久久毛片 | 国产精品色婷婷视频 | 中文字幕在线观看日本 | 久草在线一免费新视频 | 免费精品视频在线 | 欧美网址在线观看 | 欧美老女人xx | 国产一性一爱一乱一交 | 97天天干| 一级黄色片在线 | 日韩不卡高清视频 | 国产精品videossex国产高清 | 久久情侣偷拍 | 成人影音在线 | avwww在线 | 97视频在线观看播放 | 婷婷亚洲五月 | 亚洲艳情| 国产伦精品一区二区三区高清 | 992tv在线观看网站 | 中文字幕国产视频 | 日日夜夜天天久久 | 一级一片免费观看 | 国产a级免费| 天天爽天天射 | 国产精品美女久久久久久久网站 | 一二三久久久 | 成 人 黄 色 视频 免费观看 | 97国产在线播放 | 国产日韩一区在线 | 开心婷婷色 | 国产午夜精品福利视频 | 国产日韩视频在线 | 久久福利精品 | 在线三级播放 | 久久成人精品视频 | 91中文字幕一区 | 91九色国产| 91av99| a黄色片在线观看 | 99草在线视频 | 狠狠躁天天躁 | 欧美日韩国产伦理 | 国产热re99久久6国产精品 | 日韩亚洲在线 | 性色av免费观看 | 91网在线看| 91精品国产欧美一区二区 | av888av.com| 色婷婷国产精品一区在线观看 | 国产精品久久久久久久婷婷 | 成人在线免费观看网站 | 福利网在线 | 91视频最新网址 | 91精品在线观看视频 | 日韩毛片一区 | 久久高清精品 | 国产分类视频 | 视频福利在线观看 | 狠狠操欧美 | 麻豆视频在线观看 | a视频在线观看 | 2019中文字幕网站 | 日韩一区二区三区在线观看 | 午夜精品久久久久久久99无限制 | 国产精品久久久久999 | 一区二区三区在线观看中文字幕 | 黄色成人在线网站 | 91亚洲网 | 国产99免费 | 精品国产成人av在线免 | 国偷自产中文字幕亚洲手机在线 | 午夜黄色一级片 | 久草视频在线免费播放 | 国产精品va在线 | 91av电影| 亚洲,播放 | 国产精在线 | 国产亚洲字幕 | 亚洲精品国产精品久久99热 | 91在线看黄| 99色99| 久久久久久99精品 | 人人揉人人揉人人揉人人揉97 | 日韩试看 | 久草在线电影网 | 国产精品视频永久免费播放 | 精品一区三区 | 亚洲成aⅴ人在线观看 | 日韩在线视频一区二区三区 | 粉嫩av一区二区三区四区 | 99久视频 | 国产亚洲精品久久久久久电影 | 337p日本欧洲亚洲大胆裸体艺术 | 欧美乱码精品一区 | 国产成人一二片 | 久久草在线视频国产 | 九九精品视频在线看 | 国产一区二区综合 | 综合国产视频 | 亚洲男模gay裸体gay | 国产精品免费一区二区三区在线观看 | 国产精品12 | 久久网页 | 免费福利视频网站 | 免费在线观看视频a | 亚洲精品1234区 | 免费a v网站 | 国产999视频在线观看 | 69国产盗摄一区二区三区五区 | 成人超碰在线 | 日日夜夜精品网站 |