直接在Android上写入framebuffer

时间:2014-04-07 10:31:14

标签: android android-source framebuffer ioctl

我是Android 4.2.2的root手机。我想在引导加载程序代码中使用minui API(源here)来在屏幕上绘制内容。 minui比原生OpenGL简单得多,我不需要OpenGL公开的任何复杂功能。

问题在于我无法直接将内容写入fb0设备。 FBIOPUT_VSCREENINFO由于未知原因而失败。

如何在Android上直接绘制fb0,或者如何在引导加载程序模式之外使用minui

2 个答案:

答案 0 :(得分:4)

设备节点:/ dev / graphics / fb0

你可以在Android树中构建或使用arm-linux-gcc。

arm-linux-gcc -D__ANDROID__ fb-test.c -static
喜欢正常的嵌入式linux,有一个示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
struct fb_fix_screeninfo FixedInfo;
struct fb_var_screeninfo OrigVarInfo;
static int FrameBufferFD = -1;
void *FrameBuffer = (void *) -1;

#ifndef __ANDROID__
#define FRAMEBUFFER "/dev/fb0"
#else
#define FRAMEBUFFER "/dev/graphics/fb0"
#endif //__ANDROID__

void openFBDEV(void)
{
    /* open the framebuffer device */
    FrameBufferFD = open(FRAMEBUFFER, O_RDWR);
    if (FrameBufferFD < 0)
    {
        fprintf(stderr, "Error opening %s\n", FRAMEBUFFER);
        exit(1);
    }
    /* Get the fixed screen info */
    if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo))
    {
        fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed\n");
        exit(1);
    }
    /* get the variable screen info */
    if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo))
    {
        fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed\n");
        exit(1);
    }

    if (FixedInfo.visual != FB_VISUAL_TRUECOLOR
            && FixedInfo.visual != FB_VISUAL_DIRECTCOLOR)
    {
        fprintf(stderr,
                "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n",
                FixedInfo.visual);
        exit(1);
    }
    /*
     * fbdev says the frame buffer is at offset zero, and the mmio region
     * is immediately after.
     */
    /* mmap the framebuffer into our address space */
    FrameBuffer = (void *) mmap(0, /* start */
    FixedInfo.smem_len, /* bytes */
    PROT_READ | PROT_WRITE, /* prot */
    MAP_SHARED, /* flags */
    FrameBufferFD, /* fd */
    0 /* offset */);
    if (FrameBuffer == (void *) -1)
    {
        fprintf(stderr, "error: unable to mmap framebuffer\n");
        exit(1);
    }
}
void closeFBDEV(void)
{
    munmap(FrameBuffer, FixedInfo.smem_len);
    close(FrameBufferFD);
}
int main()
{
    openFBDEV();
    fprintf(stderr, "openFBDEV finish\n");
    memset(FrameBuffer, 128, FixedInfo.smem_len);
    sleep(5);
    closeFBDEV();
    fprintf(stderr, "closeFBDEV finish\n");
    return 0;
}

答案 1 :(得分:1)

源代码,测试其是否可在Qualcomm平台MSM89xx中工作:

panel_test.c

#include <unistd.h>  
#include <stdio.h>  
#include <fcntl.h>  
#include <linux/fb.h>  
#include <sys/mman.h>  
#include <stdlib.h>
#include "yellow_face.zif"
int main()  
{  
    int fbfd = 0;  
    struct fb_var_screeninfo vinfo;  
    struct fb_fix_screeninfo finfo;  
    struct fb_cmap cmapinfo;  
    long int screensize = 0;  
    char *fbp = 0;  
    int x = 0, y = 0;  
    long int location = 0;  
    int b,g,r;  
    // Open the file for reading and writing  
    fbfd = open("/dev/graphics/fb0", O_RDWR,0);                    // 打开Frame Buffer设备  
    if (fbfd < 0) {  
                printf("Error: cannot open framebuffer device.%x\n",fbfd);  
                exit(1);  
    }  
    printf("The framebuffer device was opened successfully.\n");  
  
    // Get fixed screen information  
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {            // 获取设备固有信息  
                printf("Error reading fixed information.\n");  
                exit(2);  
    }  
    printf("\ntype:0x%x\n", finfo.type );                            // FrameBuffer 类型,如0为象素  
    printf("visual:%d\n", finfo.visual );                        // 视觉类型:如真彩2,伪彩3   
    printf("line_length:%d\n", finfo.line_length );        // 每行长度  
    printf("\nsmem_start:0x%lx,smem_len:%u\n", finfo.smem_start, finfo.smem_len ); // 映象RAM的参数  
    printf("mmio_start:0x%lx ,mmio_len:%u\n", finfo.mmio_start, finfo.mmio_len );  
      
    // Get variable screen information  
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {            // 获取设备可变信息  
                printf("Error reading variable information.\n");  
                exit(3);  
    }  
    printf("%dx%d, %dbpp,xres_virtual=%d,yres_virtual=%dvinfo.xoffset=%d,vinfo.yoffset=%d\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel,vinfo.xres_virtual,vinfo.yres_virtual,vinfo.xoffset,vinfo.yoffset);  

	screensize = finfo.line_length * vinfo.yres_virtual;
    // Map the device to memory 通过mmap系统调用将framebuffer内存映射到用户空间,并返回映射后的起始地址  
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fbfd, 0);  
    if ((int)fbp == -1) {  
                printf("Error: failed to map framebuffer device to memory.\n");  
                exit(4);  
    }  
    printf("The framebuffer device was mapped to memory successfully.\n");  
/***************exampel 1**********************/
	b = 10;
	g = 100;
	r = 100;
    for ( y = 0; y < 340; y++ )
        for ( x = 0; x < 420; x++ ) { 
      
         location = (x+100) * (vinfo.bits_per_pixel/8) + 
             (y+100) * finfo.line_length; 
      
         if ( vinfo.bits_per_pixel == 32 ) {        //          
                        *(fbp + location) = b; // Some blue  
                        *(fbp + location + 1) = g;             // A little green  
                        *(fbp + location + 2) = r;             // A lot of red  
                        *(fbp + location + 3) = 0;     // No transparency  
         }
      
        }
/*****************exampel 1********************/
/*****************exampel 2********************/		
 	unsigned char *pTemp = (unsigned char *)fbp;
	int i, j;
	//起始坐标(x,y),终点坐标(right,bottom)
	x = 400;
	y = 400;
	int right = 700;//vinfo.xres;
	int bottom = 1000;//vinfo.yres;
	
	for(i=y; i< bottom; i++)
	{
		for(j=x; j<right; j++)
		{
			unsigned short data = yellow_face_data[(((i-y)  % 128) * 128) + ((j-x) %128)];
			pTemp[i*finfo.line_length + (j*4) + 2] = (unsigned char)((data & 0xF800) >> 11 << 3);
			pTemp[i*finfo.line_length + (j*4) + 1] = (unsigned char)((data & 0x7E0) >> 5 << 2);
			pTemp[i*finfo.line_length + (j*4) + 0] = (unsigned char)((data & 0x1F) << 3);
		}
	} 
/*****************exampel 2********************/	
//note:vinfo.xoffset =0 vinfo.yoffset =0 否则FBIOPAN_DISPLAY不成功
	if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {    
                printf("Error FBIOPAN_DISPLAY information.\n");  
                exit(5);  
    }  
	sleep(10);
	munmap(fbp,finfo.smem_len);//finfo.smem_len == screensize == finfo.line_length * vinfo.yres_virtual 
    close(fbfd);  
    return 0;  
}

Android.mk

# Copyright 2006-2014 The Android Open Source Project

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= panel_test.c


LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libdl liblog libbase libcutils
LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)

LOCAL_MODULE := panel_test

LOCAL_CFLAGS := -Werror

include $(BUILD_EXECUTABLE)

include $(call first-makefiles-under,$(LOCAL_PATH))

yellow_face.zif

yellow_face.zif