与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问
生活随笔
收集整理的這篇文章主要介紹了
与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
摘要:
通過一個一個framebuffer例子,復習了內存分配的應用。其中的framebuffer例子為網上流行的(確實有bug的),在編譯運行的過程中又重新溫習了好多差不多已經被遺忘的知識點,寫出來和大家分享!
---------------------------------------------------------------------------------------------------------------------
聲明:
? ? 此文為原創,歡迎轉載,轉載請保留如下信息
? ? 作者:聶飛(afreez)
? ? 聯系方式:[email]afreez@sina.com[/email] (歡迎與作者交流)
? ? 初次發布時間:2006-06-08
? ? 不經本人同意,不得用語商業或贏利性質目的,否則,作者有權追究相關責任!
-----------------------------------------------------------------------------
例子實現了直接寫屏的功能,即把屏幕清空(變黑),程序的流程大致為:打開一個FrameBuffer設備;通過mmap調用把顯卡的物理內存空間映射到用戶空間;通過映射關系直接寫內存。
頭文件
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
代碼:
#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);// pFbdev->fb==3
? ? ? ? ? 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_fix.smem_start=f0000000
? ? ? ? ? pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
// pFbdev->fb_fix.smem_len=100 0000 pFbdev->fb_mem_offset=0
// pFbdev->fb_mem =0
? ? ? ? ? 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;
? ? ? ? ? }
? ? ? ? ? //注意,下面一行有bug
? ? ? ? ? fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
? ? ? ?
? ? ? ? ? fb_close(&fbdev);
}
#endif
編譯
如果對上述代碼直接進行編譯的話,是不能成功的,即會出現類似下面的編譯錯誤
#gcc –o fbtools fbtools.c
fbtools.c: In function `main`
fbtools.c:89:warning:passing arg 1 of `fb_memset` makes pointer from integer without a cast
對有問題的fbtools.c中的第89行代碼(即加粗的有注釋的那一行)進行如下操作
修改為:
fb_memset((void *)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((void *)temp, 0, fbdev.fb_fix.smem_len);
可以成功編譯成功
而修改為:
fb_memset((&)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
會輸出:段錯誤
分析
函數原形為:void fb_memset (void *addr, int c, size_t len)
而fbtools.c:89調用時傳遞的參數為:
fb_memset(fbdev.fb_mem+fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
fbdev.fb_mem和fbdev.fb_mem_offset都是unsigned long類型的變量,它們的計算結果保存在一個臨時的棧空間,傳遞調用時,其臨時的地址是不能夠傳遞到被調用的函數的,所以編譯是同不過的。具體的可以參考內存分配的相關知識,記得《effective c++》一書里講的很詳細,可以參考。
至于修改后的:
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
編譯出現段錯誤,也是很好理解的,因為(&)temp不等于(void *)temp,也不等于
(void *)(fbdev.fb_mem+fbdev.fb_mem_offset),具體原因讀者可以對照《effective c++》思考。
通過一個一個framebuffer例子,復習了內存分配的應用。其中的framebuffer例子為網上流行的(確實有bug的),在編譯運行的過程中又重新溫習了好多差不多已經被遺忘的知識點,寫出來和大家分享!
---------------------------------------------------------------------------------------------------------------------
聲明:
? ? 此文為原創,歡迎轉載,轉載請保留如下信息
? ? 作者:聶飛(afreez)
? ? 聯系方式:[email]afreez@sina.com[/email] (歡迎與作者交流)
? ? 初次發布時間:2006-06-08
? ? 不經本人同意,不得用語商業或贏利性質目的,否則,作者有權追究相關責任!
-----------------------------------------------------------------------------
例子實現了直接寫屏的功能,即把屏幕清空(變黑),程序的流程大致為:打開一個FrameBuffer設備;通過mmap調用把顯卡的物理內存空間映射到用戶空間;通過映射關系直接寫內存。
頭文件
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
代碼:
#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);// pFbdev->fb==3
? ? ? ? ? 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_fix.smem_start=f0000000
? ? ? ? ? pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
// pFbdev->fb_fix.smem_len=100 0000 pFbdev->fb_mem_offset=0
// pFbdev->fb_mem =0
? ? ? ? ? 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;
? ? ? ? ? }
? ? ? ? ? //注意,下面一行有bug
? ? ? ? ? fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
? ? ? ?
? ? ? ? ? fb_close(&fbdev);
}
#endif
編譯
如果對上述代碼直接進行編譯的話,是不能成功的,即會出現類似下面的編譯錯誤
#gcc –o fbtools fbtools.c
fbtools.c: In function `main`
fbtools.c:89:warning:passing arg 1 of `fb_memset` makes pointer from integer without a cast
對有問題的fbtools.c中的第89行代碼(即加粗的有注釋的那一行)進行如下操作
修改為:
fb_memset((void *)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((void *)temp, 0, fbdev.fb_fix.smem_len);
可以成功編譯成功
而修改為:
fb_memset((&)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
會輸出:段錯誤
分析
函數原形為:void fb_memset (void *addr, int c, size_t len)
而fbtools.c:89調用時傳遞的參數為:
fb_memset(fbdev.fb_mem+fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
fbdev.fb_mem和fbdev.fb_mem_offset都是unsigned long類型的變量,它們的計算結果保存在一個臨時的棧空間,傳遞調用時,其臨時的地址是不能夠傳遞到被調用的函數的,所以編譯是同不過的。具體的可以參考內存分配的相關知識,記得《effective c++》一書里講的很詳細,可以參考。
至于修改后的:
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
編譯出現段錯誤,也是很好理解的,因為(&)temp不等于(void *)temp,也不等于
(void *)(fbdev.fb_mem+fbdev.fb_mem_offset),具體原因讀者可以對照《effective c++》思考。
轉載于:https://blog.51cto.com/afreez/7348
總結
以上是生活随笔為你收集整理的与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吉普赛人祖传的神奇读心术:你敢试吗?
- 下一篇: PHP 6:PHP 基本数据类型